C# 怎么把object转为Tuple类型? 强制类型转换和as的区别?

勇哥注:

今天突然发现强制类型转换和as还是有点区别的。

比如下面这句会抛异常:

其中SACItemRunStatusEnum是一个枚举。

ItemRunStatus= (Tuple<SACItemRunStatusEnum, int>)data

异常信息如下:

无法将类型为
“System.Tuple`2[Samsun.Domain.MotionCard.Common.SACItemRunStatusEnum,System.Object]”
的对象强制转换为类型
“System.Tuple`2[Samsun.Domain.MotionCard.Common.SACItemRunStatusEnum,System.Int32]”。

但是写成as就好了

ItemRunStatus= data as Tuple<SACItemRunStatusEnum, int>;

这是什么原因呢?

所以在网上查了一些资料,先放这,有时间再研究一下为啥。



2023/3/2勇哥注:

今天突然发现我上面的回答是误人子弟。

ItemRunStatus= data as Tuple<SACItemRunStatusEnum, int>;  这种转换看上去是成功了,但是结果确是null.

因此,实际本文的关键内容是“如何把object转为一个Tuple”。


在实时窗口里,敲入object变量data,可以看到是有内容的。

image.png

既然强制转换和as转换都不行,还有什么办法取出这个Item1和Item2呢?

如下图所示就可以了!!

image.png

但是它们取出的是字符串类型,因此还得转换一下。

如下:

ItemRunStatus =new Tuple<SACItemRunStatusEnum, int>(
   (SACItemRunStatusEnum)Enum.Parse(typeof(SACItemRunStatusEnum),data.GetType().GetProperty("Item1").GetValue(data, null).ToString()),
     int.Parse(data.GetType().GetProperty("Item2").GetValue(data, null).ToString())
   );

这个问题在网上是无解的,因为没有人问到过这个问题。



下面是网上的一些资料,关于强制转换与as的区别:

=========================================

What is the difference between casting and using “as” in C#?

如果存在差异,那么进行以下转换的两种方式之间有什么区别?

在这种情况下,eGridViewRowEventArgs对象。

1
2
3
GridView gv = (GridView)e.Row.FindControl("gv"); //first way

GridView gv2 = e.Row.FindControl("gv") as GridView; //second way

不同之处在于:

  • 如果强制转换失败,则会抛出

    InvalidCastException

  • 如果

    as

    运算符失败,则仅返回空引用。

  • 您不能将

    as

    与不可为空的值类型一起使用(例如,不能执行" 

    o as int

    ")。

  • 强制转换运算符还用于取消装箱。 (

    as

    可用于取消装箱为可为空的值类型。)

  • 强制转换运算符还可以执行用户定义的转换。

编辑:我已经在其他地方写过有关何时适合使用哪个运算符的文章。可能值得一读...


  • 让我用引用类型更新代码Jon。

  • 不需要太多-我已经在我的回答中解释了更多:)

  • 非常感谢,我实际上确实使用GridView更新了它,但是您的回答足够好。

  • 有几个问题,as运算符是实际的转换吗?一个比另一个快吗?

  • 我建议将问题改回不可为空的类型,因为现在,初次阅读时答案令人困惑。

  • @Paul:我会改正答案。 @Xaisoft:它们基本上彼此一样快。

  • 另一个显着差异-as运算符比强制转换运算符快得多。

  • 我将添加一个链接,因为它似乎在呼唤Jon Skeet,这很危险。 stackoverflow.com/questions/57701/

  • @不确定:我对此表示怀疑。请提供证据。请注意,使用" as"和空检查比执行" is"和强制类型转换要快,但这与说" as"比强制类型转换要快得多。

  • @不确定:如果强制转换肯定会引发异常,则执行转换会较慢,但在成功的情况下,它们基本上是相同的。另请注意,链接的答案准确地说出我对" is + cast"的处理要比" as + null check"慢。它没有说在"按原样/按铸造"成功案例中哪个更快。

  • @Jon Skeet:查找您上面提到的用户转换的成本为非零,只有前缀强制转换为零,并且是"成功"。我同意,在实例已经是强制转换类型的情况下,它们应该执行相同的操作,但这仅是一个用例。

  • @不确定:否,寻找用户转换的成本是在编译时完成的。

  • 我不是在谈论实例是实际强制类型的琐碎情况,而是在谈论任何"成功"方案。鉴于故障场景的结果是如此不同(无论是否引发异常),我认为比较那里的性能并不明智。

  • 回到用户定义的转换:如果C#编译器发出" castclass"指令而不是调用op_Explicit或op_Implicit,则转换将失败。我有一个测试应用程序,如果您想查看它,可以演示此过程。

  • @Jon Skeet-我不同意,比较这些不同的转换方法的性能非常明智,因为它们可以并且通常用于运行时类型检查的相同目的。

  • @Jon Skeet-顺便说一句,您似乎在这里与自己矛盾:blogs.msdn.com/csharpfaq/archive/2004/03/12/88420.aspx。"与铸造相比,在Microsoft CLR的v1.0和v1.1中,as运算符似乎要快一些,"除非以后的CLR版本中有所更改。

  • @不确定:我很确定它已经改变了。无论哪种方式,按照您最初的主张,它肯定不会"显着更快"。如果您愿意,我们可以对其进行基准测试。

  • @不确定:如果目的只是为了检查执行时间,那么您当然不应该进行强制转换,然后大概捕获异常。那太疯狂了。如果您只想检查,请使用"是"。如果要检查然后使用新类型的值,请使用" as",然后使用空检查。

  • 如果要使用新类型,并且想要异常类型错误的异常(因为这表明您的情况在某些代码中存在错误),请使用强制转换。对我来说似乎很简单。

  • @Jon Skeet:争论不是关于哪种用例的适当性,而是关于特定用例下的性能差异,这是通常的做法,无论您和我是否更了解。

  • 仅当结果相同时才比较性能。我不认为Xaisoft询问哪个更快时,他询问的是失败案例。显而易见,异常比返回null慢。

  • 因此,您是否声称当强制转换和" as"都成功(即返回非空引用)时," as"要快得多?

  • 在我的原始帖子中大量使用形容词是错误的,但仍然比前缀更快。 用您的话来说,CLR 1.0 / 1.1的区别很小。 我用3.5进行的测试表明差异仍然存在,但可以忽略不计。 谷歌搜索" C#铸造性能"证实了这一点。

  • 好的,我对此很满意。 我当然不会对"它更快但只有一点点"提出异议。"显着"给人错误的印象。 我松了一口气,看到我本来就允许自己有一些回旋余地,说他们彼此之间"快" :)




上面的答案中没有提到的是目的-为什么要执行转换,(更重要的是)转换后的行会发生什么?

例如,我多次看到类似于以下代码的代码:

if ((foo as SomeType).SomeMethod()) { /* ... */ }

可以将其与使用强制转换的版本进行比较:

if (((SomeType) foo).SomeMethod()) { /* ... */ }

那么,哪个更好?

演员是。

如果转换失败,则使用as将导致NullReferenceException

如果转换失败,则使用强制类型转换将导致InvalidCastException

现在告诉我,哪个是调试更有用的例外? NullReferenceException(几乎可以由任何东西产生)或InvalidCastException(可以让您知道实际出了什么问题)?

因此,仅当转换实际上是可选的时才使用as(这意味着在使用变量之前必须进行null检查)。否则,请使用强制转换,从而使您的意图更加明确。


安全投为

1
variable as type

与...相同

1
(variable is type) ? (type)variable : (type)null

并且不适用于值类型。


" as"语句基本上会尝试转换该变量,如果失败则返回null而不是引发异常。因此,您要强制转换为的值必须可以为空-引用类型或可为空的原语。在您的示例中,您必须执行以下操作:

1
int? i2 = o as int;

否则将无法编译。


通常,静态类型转换与" as"之间的区别在于,如果转换失败,则类型转换将引发Exception,而" as"仅将变量设置为null。


除了Jon指出的问题外,as关键字有效地将o强制转换为SomeClass。如果o不是从SomeClass派生的,则返回null。而简单的强制转换会引发异常。

1
SomeClass i2 = o as SomeClass;

1
2
3
4
5
SomeClass i2;
if (is SomeClass)
    i2 = (SomeClass)o;
else
    i2 = null;


但是,如果您使用引用类型,则说Table,则第一个将引发InvalidCastException,以防无法将o分配给Table,而第二个将仅返回null。

我可能会在这里说明显而易见的内容,但是使用" as"强制转换可以得到的一件事是,可以确保最终得到您请求的类型的对象。
在某些情况下这很方便。





本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:
本帖最后由 勇哥,很想停止 于 2023-02-28 14:48:25 编辑

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864