C# 即使没有空检查,使用“as”代替强制转换是否有意义?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2139798/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 23:50:14  来源:igfitidea点击:

Does it make sense to use "as" instead of a cast even if there is no null check?

c#castingtype-conversion

提问by Heinzi

In development blogs, online code examples and (recently) even a book, I keep stumbling about code like this:

在开发博客、在线代码示例和(最近)甚至一本书中,我不断遇到这样的代码:

var y = x as T;
y.SomeMethod();

or, even worse:

或者,更糟糕的是:

(x as T).SomeMethod();

That doesn't make sense to me. If you are sure that xis of type T, you should use a direct cast: (T)x. If you are not sure, you can use asbut need to check for nullbefore performing some operation. All that the above code does is to turn a (useful) InvalidCastExceptioninto a (useless) NullReferenceException.

这对我来说没有意义。如果您确定它x是 type T,则应该使用直接强制转换:(T)x。如果您不确定,您可以使用,asnull在执行某些操作之前需要检查。上面代码所做的就是将 (有用的)InvalidCastException变成 (无用的) NullReferenceException

Am I the only one who thinks that this a blatant abuse of the askeyword? Or did I miss something obvious and the above pattern actually makes sense?

只有我认为这是对as关键字的公然滥用吗?还是我错过了一些明显的东西,而上述模式实际上是有道理的?

采纳答案by Mehrdad Afshari

Your understanding is true. That sounds like trying to micro-optimize to me. You should use a normal cast when you are sure of the type. Besides generating a more sensible exception, it also fails fast. If you're wrong about your assumption about the type, your program will fail immediately and you'll be able to see the cause of failure immediately rather than waiting for a NullReferenceExceptionor ArgumentNullExceptionor even a logical error sometime in the future. In general, an asexpression that's not followed by a nullcheck somewhere is a code smell.

你的理解是对的。这听起来像是在尝试对我进行微优化。当您确定类型时,您应该使用普通类型转换。除了生成更合理的异常之外,它也会快速失败。如果你错了你对类型的假设,你的程序将立即失败,你就可以看到失败立即,而不是等待的原因一个NullReferenceException或者ArgumentNullException甚至是一个逻辑上的错误在未来的某个时候。一般来说,一个as没有在null某处进行检查的表达式是一种代码异味。

On the other hand, if you are not sure about the cast and expect it to fail, you should use asinstead of a normal cast wrapped with a try-catchblock. Moreover, use of asis recommended over a type check followed by a cast. Instead of:

另一方面,如果您不确定演员表并预计它会失败,您应该使用astry-catch块包裹的普通演员表代替。此外,as建议使用 of而不是类型检查,然后是强制转换。代替:

if (x is SomeType)
   ((SomeType)x).SomeMethod();

which generates an isinstinstructionfor the iskeyword, and a castclassinstructionfor the cast (effectively performing the cast twice), you should use:

其产生的isinst指令is关键字,和castclass指令的投(有效执行转换两次),你应该使用:

var v = x as SomeType;
if (v != null)
    v.SomeMethod();

This only generates an isinstinstruction. The former method has a potential flaw in multithreaded applications as a race condition might cause the variable to change its type after the ischeck succeeded and fail at the cast line. The latter method is not prone to this error.

这只会生成一条isinst指令。前一种方法在多线程应用程序中存在潜在缺陷,因为竞争条件可能会导致变量在is检查成功后更改其类型并在强制转换行失败。后一种方法不易出现此错误。



The following solution is not recommendedfor use in production code. If you really hate such a fundamental construct in C#, you might consider switching to VB or some other language.

不建议在生产代码中使用以下解决方案。如果您真的讨厌 C# 中的这种基本结构,您可以考虑切换到 VB 或其他一些语言。

In case one desperately hates the cast syntax, he/she can write an extension method to mimic the cast:

如果有人非常讨厌强制转换语法,他/她可以编写一个扩展方法来模拟强制转换:

public static T To<T>(this object o) { // Name it as you like: As, Cast, To, ...
    return (T)o;
}

and use a neat[?] syntax:

并使用简洁的 [?] 语法:

obj.To<SomeType>().SomeMethod()

回答by Rubens Farias

IMHO, asjust make sense when combined with a nullcheck:

恕我直言,asnull支票结合使用才有意义:

var y = x as T;
if (y != null)
    y.SomeMethod();

回答by Joey

The direct cast needs a pair of parentheses more than the askeyword. So even in the case where you're 100 % sure what the type is, it reduces visual clutter.

直接转换比as关键字需要更多的括号。因此,即使您 100% 确定类型是什么,它也会减少视觉混乱。

Agreed on the exception thing, though. But at least for me, most uses of asboil down to check for nullafterwards, which I find nicer than catching an exception.

不过,同意例外的事情。但至少对我来说,大多数情况下,asbelow down 用于null事后检查,我发现这比捕获异常更好。

回答by Max Galkin

99% of the time when I use "as" is when I'm not sure what's the actual object type

当我使用“as”时,99% 的情况下我不确定实际的对象类型是什么

var x = obj as T;
if(x != null){
 //x was type T!
}

and I don't want to catch explicit cast exceptions nor make cast twice, using "is":

并且我不想捕获显式转换异常,也不想使用“is”进行两次转换:

//I don't like this
if(obj is T){
  var x = (T)obj; 
}

回答by Andrew Garrison

I believe that the askeyword could be thought of as a more elegant looking version of the dynamic_castfrom C++.

我相信该as关键字可以被认为是dynamic_castC++ 中看起来更优雅的版本 。

回答by JulianR

It's just because people like the way it looks, it's very readable.

只是因为人们喜欢它的外观,它的可读性很强。

Lets face it: the casting/conversion operator in C-like languages is pretty terrible, readability-wise. I would like it better if C# adopted either the Javascript syntax of:

让我们面对现实吧:类 C 语言中的转换/转换操作符非常糟糕,在可读性方面。如果 C# 采用以下 Javascript 语法,我会更好:

object o = 1;
int i = int(o);

Or define a tooperator, the casting equivalent of as:

或者定义一个to运算符,相当于as

object o = 1;
int i = o to int;

回答by Jla

It's probably more popular for no technical reason but just because it's easier to read and more intuitive. (Not saying it makes it better just trying to answer the question)

它可能更受欢迎没有技术原因,而只是因为它更容易阅读和更直观。(并不是说它只是试图回答这个问题让它变得更好)

回答by Bob

People likeasso much because it makes them feel safe from exceptions... Like guarantee on a box. A guy puts a fancy guarantee on the box 'cause he wants you to feel all warm and toasty inside. You figure you put that little box under your pillow at night, the Guarantee Fairy might come down and leave a quarter, am I right Ted?

人们非常喜欢as它,因为它让他们感到安全,不受例外的影响……就像盒子上的保证一样。一个男人在盒子上放了一个花哨的保证,因为他希望你在里面感到温暖和温暖。你认为你晚上把那个小盒子放在枕头下,保证仙女可能会下来留下四分之一,对吗泰德?

Back on topic... when using a direct cast, there is the possibilityfor an invalid cast exception. So people apply asas a blanket solution to all of their casting needs because as(by itself) will never throw an exception. But the funny thing about that, is in the example you gave (x as T).SomeMethod();you are trading an invalid cast exception for a null reference exception. Which obfuscates the real problem when you see the exception.

回到主题......使用直接强制转换时,可能会出现无效的强制转换异常。所以人们将其as作为一个全面的解决方案来满足他们所有的铸造需求,因为as(本身)永远不会抛出异常。但有趣的是,在您提供的示例中,(x as T).SomeMethod();您正在将无效的强制转换异常换成空引用异常。当您看到异常时,这会混淆真正的问题。

I generally don't use astoo much. I prefer the istest because to me, it appears more readable and makes more sense then trying a cast and checking for null.

我一般不会用as太多。我更喜欢这个is测试,因为对我来说,它看起来更具可读性,而且比尝试强制转换和检查 null 更有意义。

回答by Joe

I've often seen references to this misleading articleas evidence that "as" is faster than casting.

我经常看到对这篇误导性文章的引用作为“as”比强制转换更快的证据。

One of the more obvious misleading aspects of this article is the graphic, which does not indicate what is being measured: I suspect it's measuring failedcasts (where "as" is obviously much faster as no exception is thrown).

本文中更明显的误导性方面之一是图形,它没有表明正在测量什么:我怀疑它正在测量失败的强制转换(其中“as”显然要快得多,因为没有抛出异常)。

If you take the time to do the measurements, then you'll see that casting is, as you'd expect, fasterthan "as" when the cast succeeds.

如果您花时间进行测量,那么您会发现,正如您所期望的那样,当转换成功时,转换比“as”

I suspect this may be one reason for "cargo cult" use of the as keyword instead of a cast.

我怀疑这可能是“货物崇拜”使用 as 关键字而不是演员表的原因之一。

回答by Rauhotz

One reason for using "as":

使用“as”的原因之一:

T t = obj as T;
 //some other thread changes obj to another type...
if (t != null) action(t); //still works

Instead of (bad code):

而不是(坏代码):

if (obj is T)
{
     //bang, some other thread changes obj to another type...
     action((T)obj); //InvalidCastException
}