C# “使用”有意义吗;作为「;而不是强制转换,即使没有空检查?
在开发博客、在线代码示例和(最近)甚至一本书中,我总是对这样的代码结结巴巴:C# “使用”有意义吗;作为「;而不是强制转换,即使没有空检查?,c#,casting,type-conversion,C#,Casting,Type Conversion,在开发博客、在线代码示例和(最近)甚至一本书中,我总是对这样的代码结结巴巴: var y = x as T; y.SomeMethod(); 或者,更糟糕的是: (x as T).SomeMethod(); 这对我来说没有意义。如果您确定x属于T类型,则应使用直接转换:(T)x。如果不确定,可以将用作,但需要在执行某些操作之前检查null。上述代码所做的只是将(有用的)InvalidCastException转换为(无用的)NullReferenceException 我是唯一一个认为这是公
var y = x as T;
y.SomeMethod();
或者,更糟糕的是:
(x as T).SomeMethod();
这对我来说没有意义。如果您确定x
属于T
类型,则应使用直接转换:(T)x
。如果不确定,可以将用作
,但需要在执行某些操作之前检查null
。上述代码所做的只是将(有用的)InvalidCastException
转换为(无用的)NullReferenceException
我是唯一一个认为这是公然滥用
作为
关键字的人吗?还是我错过了一些明显的东西,而上面的模式实际上是有意义的?你的理解是正确的。对我来说,这听起来像是在尝试微优化。确定类型后,应使用普通类型转换。除了生成更合理的异常之外,它还很快失败。如果您对类型的假设是错误的,那么您的程序将立即失败,并且您将能够立即看到失败的原因,而不是等待NullReferenceException
或ArgumentNullException
甚至将来某个时候出现逻辑错误。一般来说,as
表达式后面没有null
检查的地方是代码气味
另一方面,如果您对强制转换不确定,并预期它会失败,则应使用as
而不是用try catch
块包装的普通强制转换。此外,建议使用作为
,而不是先进行类型检查,然后进行强制转换。而不是:
if (x is SomeType)
((SomeType)x).SomeMethod();
这会为is
关键字生成一个,为强制转换生成一个(有效地执行强制转换两次),您应该使用:
var v = x as SomeType;
if (v != null)
v.SomeMethod();
这只会生成一条isinst
指令。前一种方法在多线程应用程序中有一个潜在的缺陷,因为竞争条件可能会导致变量在检查成功且在强制转换行失败后更改其类型。后一种方法不容易出现这种错误
不建议在生产代码中使用以下解决方案。如果你真的讨厌C语言中的一个基本结构,你可以考虑切换到VB或其他语言。
如果一个人非常讨厌cast语法,他/她可以编写一个扩展方法来模拟cast:
public static T To<T>(this object o) { // Name it as you like: As, Cast, To, ...
return (T)o;
}
publicstatict To(这个对象o){//随意命名:as,Cast,To。。。
返回(T)o;
}
并使用简洁的[?]语法:
obj.To<SomeType>().SomeMethod()
obj.To().SomeMethod()
IMHO,作为
仅在与null
检查组合时才有意义:
var y = x as T;
if (y != null)
y.SomeMethod();
直接转换比as
关键字更需要一对括号。因此,即使在你100%确定类型的情况下,它也会减少视觉混乱
不过,我还是同意了例外情况。但至少对我来说,as
的大多数用法归结为事后检查null
,我发现这比捕获异常要好。99%使用“as”的时候,我不确定实际的对象类型
var x = obj as T;
if(x != null){
//x was type T!
}
我不想捕捉显式强制转换异常,也不想使用“is”进行两次强制转换:
我相信as
关键字可以被认为是
<代码>动态> C++, 这只是因为人们喜欢它的样子,它非常可读。
让我们面对现实:类C语言中的强制转换/转换操作符非常糟糕,可读性非常好。我更希望C#采用以下Javascript语法之一:
object o = 1;
int i = int(o);
或者定义一个to
操作符,将的转换等价物定义为
:
object o = 1;
int i = o to int;
它之所以更受欢迎,可能不是因为技术原因,而是因为它更容易阅读,更直观。(不说这会让回答问题变得更好)人们非常喜欢as
,因为这会让他们感觉不受异常的影响。。。就像盒子上的保证。一个家伙在盒子上放了一张精美的保证书,因为他想让你在里面感到温暖和温暖。你以为你晚上把那个小盒子放在枕头下,仙女就会下来留下一个25美分的硬币,对吗,泰德
回到话题上来。。。使用直接强制转换时,可能会出现无效强制转换异常。因此,人们将as
作为一种综合解决方案应用于他们所有的铸造需求,因为as
(本身)永远不会引发异常。但有趣的是,在您给出的示例中,(x为T).SomeMethod()代码>您正在用无效强制转换异常交换空引用异常。当您看到异常时,它会混淆真正的问题
我一般不会把用作太多。我更喜欢is
测试,因为对我来说,它比尝试强制转换和检查null更具可读性和意义 我经常看到有人提到“as”比casting快
这篇文章中一个更明显的误导性方面是图形,它没有指出要度量的内容:我怀疑它度量的是失败的强制转换(其中“as”显然要快得多,因为没有抛出异常)
如果您花时间进行测量,那么您将看到,正如您所期望的,当转换成功时,转换比“as”更快
我怀疑这可能是“cargo cult”使用as关键字而不是演员阵容的一个原因。使用“as”的一个原因:
而不是(错误代码):
这一定是我的工作之一
Stroustrup的D&E和/或我现在找不到的一些博客文章讨论了to
操作符的概念,该操作符将解决所提出的问题(即,与的语法相同,但具有DirectCast
语义)
之所以没有实现,是因为演员阵容会带来痛苦和丑陋,所以你会失败
object o = 1;
int i = o to int;
T t = obj as T;
//some other thread changes obj to another type...
if (t != null) action(t); //still works
if (obj is T)
{
//bang, some other thread changes obj to another type...
action((T)obj); //InvalidCastException
}