当前位置:  开发笔记 > 编程语言 > 正文

即使没有空检查,使用"as"而不是强制转换是否有意义?

如何解决《即使没有空检查,使用"as"而不是强制转换是否有意义?》经验,为你挑选了10个好方法。

在开发博客,在线代码示例和(最近)甚至是一本书中,我一直在寻找像这样的代码:

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

或者更糟糕的是:

(x as T).SomeMethod();

这对我来说没有意义.如果你确定它x是类型T,你应该使用直接演员:(T)x.如果您不确定,可以使用as但需要null在执行某些操作之前进行检查.以上代码所做的就是将(有用)InvalidCastException变为(无用)NullReferenceException.

我是唯一一个认为这是公然滥用as关键字的人吗?还是我错过了一些明显的东西,上面的模式实际上有意义?



1> Mehrdad Afsh..:

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

另一方面,如果你不确定演员并且期望它失败,你应该使用as而不是用try-catch块包裹的普通演员.此外,as建议使用类型检查,然后进行强制转换.代替:

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

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

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

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


建议不要在生产代码中使用以下解决方案.如果你真的讨厌C#中这样一个基本的构造,你可以考虑切换到VB或其他语言.

如果一个人极度讨厌强制转换语法,他/她可以编写一个扩展方法来模仿强制转换:

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

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

obj.To().SomeMethod()


@RMorrisey:我至少有一个例子:假设你有一个`cache`对象,另一个线程试图通过将它设置为`null`来使它无效.在无锁的场景中,可能会出现这些东西.
is + cast足以触发来自FxCop的"不要不必要地施放"警告:http://msdn.microsoft.com/en-us/library/ms182271.aspx这应该是避免构造的足够理由.
我认为竞争条件无关紧要.如果您遇到此问题,那么您的代码不是线程安全的,并且有更可靠的方法来解决它而不是使用关键字"as".其余答案为+1.
你应该避免在`Object`上创建扩展方法.在值类型上使用该方法将导致它被不必要地装箱.
@MgSam显然,这样的用例对于这里的`To`方法没有意义,因为它只能转换到继承层次结构,对于值类型而言,无论如何都涉及到拳击.当然,整个想法更具理论性而非严肃性.

2> Rubens Faria..:

恕我直言,as结合null支票时才有意义:

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



3> Larry Fix..:

使用'as'不会应用用户定义的转换,而演员将在适当的时候使用它们.在某些情况下,这可能是一个重要的区别.


这一点很重要.Eric Lippert在此处进行了讨论:http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx
好评,P!但是,如果你的代码依赖于这种区别,我会说你将来会有一个深夜的调试会话.

4> Eric Lippert..:

我在这里写了一些关于此的内容:

http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx

我理解你的观点.我同意它的主旨:一个演员操作员传达"我确信这个对象可以转换为那种类型,如果我错了,我愿意冒一个例外",而"as"运算符进行通信"我不确定这个对象是否可以转换为那种类型;如果我错了就给我一个空".

但是,有一个微妙的区别.(x为T).Whatever()传达"我不仅知道x可以转换为T,而且这样做只涉及引用或拆箱转换,而且x不是空".这确实传达了与((T)x)不同的信息.无论什么(),也许这就是代码作者的意图.


好吧,也许*大多数*代码的作者都不会做出那种微妙的区分.我个人可能是,但如果我是,我会添加评论这个效果.

5> Joe..:

我经常看到这篇误导性文章的引用作为"as"比铸造更快的证据.

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

如果你花时间进行测量,那么你会发现,正如你所期望的那样,铸造比铸造成功时的"as" 更快.

我怀疑这可能是"货物崇拜"使用as关键字而不是演员表的一个原因.


感谢您的链接,这非常有趣.根据我对文章的理解,他**比较非例外情况.尽管如此,这篇文章是为.net 1.1编写的,评论指出这在.net 2.0中有所改变:性能现在几乎相等,前缀甚至更快.

6> Joey..:

直接投射比as关键字需要一对括号.因此,即使在您100%确定类型是什么的情况下,它也可以减少视觉混乱.

但是就异常事项达成了一致意见.但至少对我而言,大多数使用as煮沸null以后检查,我觉得比捕捉异常更好.



7> Max Galkin..:

当我使用"as"时,99%的时间是我不确定实际对象类型是什么时候

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

并且我不想捕获显式的强制转换异常,也不想使用"is"进行两次强制转换:

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


您刚刚为`as`描述了正确的用例.另外1%是什么?
+1我同意称之为与Rubens Farias的答案一样有价值 - 人们希望能来到这里,这将是一个有用的例子

8> JulianR..:

这只是因为人们喜欢它的外观,它非常易读.

让我们面对现实:C语言中的转换/转换运算符非常可怕,可读性方面.如果C#采用以下Javascript语法,我希望它更好:

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

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

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



9> Bob..:

人们喜欢as这么多,因为它让他们感到安全,不受例外的影响...就像盒子上的保证一样.一个人在盒子上放了一个奇特的保证,因为他希望你感觉内心温暖和温暖.你认为你晚上把那个小盒子放在你的枕头下,保证仙女可能会下来并离开四分之一,我是不是特德?

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

我一般不会用as太多.我更喜欢is测试,因为对我来说,它看起来更具可读性,然后尝试演员和检查null更有意义.


"我更喜欢is test" - "is"后跟一个强制转换当然比"as"慢,然后是null测试(就像"IDictionary.ContainsKey",然后使用索引器解除引用比"IDictionary.TryGetValue慢" ").但如果你发现它更具可读性,毫无疑问差异很小.

10> Ruben Bartel..:

这必须是我最大的烦恼之一.

Stroustrup的d&E和/或一些博客文章中,我找不到,现在讨论一个概念to操作这就解决所作出的点/sf/ask/17360801/(即,相同的语法,as但是DirectCast语义).

这没有得到实施的原因是因为演员阵容应该引起痛苦并且丑陋,所以你不能使用它.

遗憾的是,"聪明"的程序员(通常是书籍作者(Juval Lowy IIRC))as以这种方式滥用(C++不提供as,可能是出于这个原因).

即使VB在具有一致的语法,迫使你选择一个更具一致性TryCastDirectCast让你的心!

推荐阅读
oDavid_仔o_880
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有