What's the point of “As” keyword in C#
来自文档:
The as operator is like a cast except that it yields null on conversion failure instead of raising an exception. More formally, an expression of the form:
1 expression as typeis equivalent to:
1except that expression is evaluated only once.
所以你为什么不选择这样或那样做呢?为什么有两个铸造系统?
他们不是两个铸造系统。这两个词的作用相似,但含义却截然不同。"as"的意思是"我认为这个对象实际上可能是另一种类型;如果不是,请给我空值。"强制转换表示两种情况之一:
我确信这个物体实际上是另一种类型。这样做吧,如果我错了,就让程序崩溃。
我确信这个对象不是其他类型的,但是有一种众所周知的方法可以将当前类型的值转换为所需类型。(例如,将int转换为short。)这样做,如果转换实际上不起作用,程序就会崩溃。
有关更多详细信息,请参阅我关于这个主题的文章。
http://blogs.msdn.com/b/ericlippet/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx
效率和性能
执行强制转换的一部分是一些集成的类型检查;因此用显式类型检查预先固定实际强制转换是多余的(类型检查会发生两次)。使用
1 2 3 4 5 |
进行2次检查,而
1 2 3 4 5 | SomeType y = x as SomeType; if (y != null) { // Do something } |
使1X——与类型检查相比,空检查非常便宜。
因为有时候,如果你不能像你期望的那样投射,你希望事情失败;有时候,你不在乎,如果一个给定的物体不能投射,你只想丢弃它。
它基本上是用try块包装的常规强制转换的更快版本;但是
它允许快速检查,而无需尝试/强制转换开销,在某些情况下,处理基于消息的继承树可能需要这种开销。
我经常使用它(输入消息,对特定的子类型作出反应)。Try/Cast速度会明显慢一些(许多尝试/捕获每一条消息的帧),我们在这里讨论每秒处理200000条消息。
让我给你一个真实的场景,你将在哪里使用这两个。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class Foo { private int m_Member; public override bool Equals(object obj) { // We use 'as' because we are not certain of the type. var that = obj as Foo; if (that != null) { return this.m_Member == that.m_Member; } return false; } } |
还有…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class Program { public static void Main() { var form = new Form(); form.Load += Form_Load; Application.Run(form); } private static void Form_Load(object sender, EventArgs args) { // We use an explicit cast here because we are certain of the type // and we want an exception to be thrown if someone attempts to use // this method in context where sender is not a Form. var form = (Form)sender; } } |
我通常根据代码的语义选择其中一个。
例如,如果您有一个
如果您不确定对象是特定类型,但希望在对象是特定类型时具有逻辑性,请使用
也许例子会有帮助:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | // Regular casting Class1 x = new Class1(); Class2 y = (Class2)x; // Throws exception if x doesn't implement or derive from Class2 // Casting with as Class2 y = x as Class2; // Sets y to null if it can't be casted. Does not work with int to short, for example. if (y != null) { // We can use y } // Casting but checking before. // Only works when boxing/unboxing or casting to base classes/interfaces if (x is Class2) { y = (Class2)x; // Won't fail since we already checked it // Use y } // Casting with try/catch // Works with int to short, for example. Same as"as" try { y = (Class2)x; // Use y } catch (InvalidCastException ex) { // Failed cast } |