Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “使用”有意义吗;作为「;而不是强制转换,即使没有空检查?_C#_Casting_Type Conversion - Fatal编程技术网

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
}