Hei*_*nzi 350 c# casting type-conversion
在开发博客,在线代码示例和(最近)甚至是一本书中,我一直在寻找像这样的代码:
var y = x as T;
y.SomeMethod();
Run Code Online (Sandbox Code Playgroud)
或者更糟糕的是:
(x as T).SomeMethod();
Run Code Online (Sandbox Code Playgroud)
这对我来说没有意义.如果你确定它x
是类型T
,你应该使用直接演员:(T)x
.如果您不确定,可以使用as
但需要null
在执行某些操作之前进行检查.以上代码所做的就是将(有用)InvalidCastException
变为(无用)NullReferenceException
.
我是唯一一个认为这是公然滥用as
关键字的人吗?还是我错过了一些明显的东西,上面的模式实际上有意义?
Meh*_*ari 251
你的理解是真的.这听起来像是试图对我进行微观优化.当您确定类型时,应该使用普通的强制转换.除了产生更明智的例外,它也会快速失败.如果你错了你对类型的假设,你的程序将立即失败,你就可以看到失败的原因立即而不是等待NullReferenceException
或者ArgumentNullException
甚至是一个逻辑错误在将来某个时候.通常,在某处as
没有null
检查的表达式是代码气味.
另一方面,如果你不确定演员并且期望它失败,你应该使用as
而不是用try-catch
块包裹的普通演员.此外,as
建议使用类型检查,然后进行强制转换.代替:
if (x is SomeType)
((SomeType)x).SomeMethod();
Run Code Online (Sandbox Code Playgroud)
其产生的isinst
指令为is
关键字,和castclass
指令的投(有效执行转换两次),你应该使用:
var v = x as SomeType;
if (v != null)
v.SomeMethod();
Run Code Online (Sandbox Code Playgroud)
这只会生成一条isinst
指令.前一种方法在多线程应用程序中存在潜在缺陷,因为竞争条件可能导致变量在is
检查成功后更改其类型并在转换线处失败.后一种方法不容易出现这种错误.
建议不要在生产代码中使用以下解决方案.如果你真的讨厌C#中这样一个基本的构造,你可以考虑切换到VB或其他语言.
如果一个人极度讨厌强制转换语法,他/她可以编写一个扩展方法来模仿强制转换:
public static T To<T>(this object o) { // Name it as you like: As, Cast, To, ...
return (T)o;
}
Run Code Online (Sandbox Code Playgroud)
并使用整洁的[?]语法:
obj.To<SomeType>().SomeMethod()
Run Code Online (Sandbox Code Playgroud)
Rub*_*ias 42
恕我直言,as
结合null
支票时才有意义:
var y = x as T;
if (y != null)
y.SomeMethod();
Run Code Online (Sandbox Code Playgroud)
Lar*_*Fix 39
使用'as'不会应用用户定义的转换,而演员将在适当的时候使用它们.在某些情况下,这可能是一个重要的区别.
Eri*_*ert 36
我在这里写了一些关于此的内容:
我理解你的观点.我同意它的主旨:一个演员操作员传达"我确信这个对象可以转换为那种类型,如果我错了,我愿意冒一个例外",而"as"运算符进行通信"我不确定这个对象是否可以转换为那种类型;如果我错了就给我一个空".
但是,有一个微妙的区别.(x为T).Whatever()传达"我不仅知道x可以转换为T,而且这样做只涉及引用或拆箱转换,而且x不是空".这确实传达了与((T)x)不同的信息.无论什么(),也许这就是代码作者的意图.
Joe*_*oey 11
直接投射比as
关键字需要一对括号.因此,即使在您100%确定类型是什么的情况下,它也可以减少视觉混乱.
但是就异常事项达成了一致意见.但至少对我而言,大多数使用as
煮沸null
以后检查,我觉得比捕捉异常更好.
当我使用"as"时,99%的时间是我不确定实际对象类型是什么时候
var x = obj as T;
if(x != null){
//x was type T!
}
Run Code Online (Sandbox Code Playgroud)
并且我不想捕获显式的强制转换异常,也不想使用"is"进行两次强制转换:
//I don't like this
if(obj is T){
var x = (T)obj;
}
Run Code Online (Sandbox Code Playgroud)
这只是因为人们喜欢它的外观,它非常易读.
让我们面对现实:C语言中的转换/转换运算符非常可怕,可读性方面.如果C#采用以下Javascript语法,我希望它更好:
object o = 1;
int i = int(o);
Run Code Online (Sandbox Code Playgroud)
或者定义一个to
运算符,相当于as
:
object o = 1;
int i = o to int;
Run Code Online (Sandbox Code Playgroud)
人们喜欢as
这么多,因为它让他们感到安全,不受例外的影响...就像盒子上的保证一样.一个人在盒子上放了一个奇特的保证,因为他希望你感觉内心温暖和温暖.你认为你晚上把那个小盒子放在你的枕头下,保证仙女可能会下来并离开四分之一,我是不是特德?
回到主题...当使用直接强制转换时,可能存在无效的强制转换异常.所以人们将其as
作为一个全面的解决方案应用于他们所有的铸造需求,因为as
(本身)永远不会抛出异常.但有趣的是,在你给(x as T).SomeMethod();
你的示例中,为空引用异常交易了一个无效的强制转换异常.当您看到异常时,会混淆真正的问题.
我一般不会用as
太多.我更喜欢is
测试,因为对我来说,它看起来更具可读性,然后尝试演员和检查null更有意义.
这必须是我最大的烦恼之一.
Stroustrup的d&E和/或一些博客文章中,我找不到,现在讨论一个概念to
操作这就解决所作出的点/sf/users/5114931/(即,相同的语法,as
但是DirectCast
语义).
这没有得到实施的原因是因为演员阵容应该引起痛苦并且丑陋,所以你不能使用它.
遗憾的是,"聪明"的程序员(通常是书籍作者(Juval Lowy IIRC))as
以这种方式滥用(C++不提供as
,可能是出于这个原因).
即使VB在具有一致的语法,迫使你选择一个更具一致性TryCast
或DirectCast
和让你的心!