C#中“As”关键字的含义是什么
从文档:
as运算符就像一个强制转换,除了在转换失败时产生空值而不是引发exception。 更正式的expressionforms是:
expression as type
相当于:
expression is type ? (type)expression : (type) null
除了expression式只评估一次。
那你为什么不select这样做呢? 为什么有两个铸造系统?
他们不是两个铸造系统。 两者有类似的行为,但意义却非常不同。 一个“as”的意思是“我认为这个对象实际上可能是这个types的,如果不是,就给我null”。 演员意味着两件事之一:
-
我确切地知道这个对象实际上是另一种types的。 这样做,如果我错了,程序崩溃。
-
我确定这个对象不是这个types的,但是有一个众所周知的将当前types的值转换为所需types的方法。 (例如,铸造int简称。)如此,如果转换不实际工作,崩溃程序。
有关更多详细信息,请参阅我的文章。
因为有时候,如果你不能像预期的那样施展任何东西,那么你就想要失败,而其他时候你不关心,只是想放弃一个给定的对象,如果它不能施放的话。
它基本上是一个包含在try块中的常规转换的更快的版本; 但是它更可读,也可以节省打字的时间。
效率和性能
执行演员的一部分是一些综合types检查; 所以用明确的types检查在实际转换前加上冗余(types检查会发生两次)。 使用as
关键字可确保只执行一次types检查。 你可能会想“但它必须做一个空检查,而不是第二个types检查”,但与types检查相比,空检查是非常有效和高效的。
if (x is SomeType ) { SomeType y = (SomeType )x; // Do something }
进行2次检查,而
SomeType y = x as SomeType; if (y != null) { // Do something }
使1x – 与types检查相比,空检查非常便宜。
它允许快速检查而不用尝试/转换开销,在某些情况下可能需要处理基于消息的inheritance树。
我使用它很多(得到一个消息,对特定的子types作出反应)。 尝试/播放会显着变慢(每条消息都有很多尝试/抓取帧) – 我们在这里讨论每秒处理200.000条消息。
我通常根据代码的语义select一个或另一个。
例如,如果你有一个object
,你知道它必须是一个string
然后使用(string)
因为这表示,编写代码的人确定该对象是一个string
,如果它不是比我们已经有更大的问题比将抛出的运行时强制转换exception。
如果您不确定该对象是否属于特定types,但是希望具有逻辑时间,请使用它。 您可以使用is
运算符,然后使用cast,但是as
运算符更有效。
让我给你真实世界的场景,你会使用两个。
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; } }
和…
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; } }
也许例子会有所帮助:
// 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 }