C#“as”演员与经典演员

时间:2011-02-07 21:15:28

标签: c# casting

  

可能重复:
  Casting vs using the ‘as’ keyword in the CLR

我最近了解了一种不同的演员方式。而不是使用

SomeClass someObject = (SomeClass) obj;

可以使用以下语法:

SomeClass someObject = obj as SomeClass;

如果obj不是SomeClass,它似乎返回null,而不是抛出一个类转换异常。

我发现如果转换失败并且我尝试访问someObject变量,这会导致NullReferenceException。所以我想知道这种方法背后的理由是什么?为什么要使用这种方式而不是(旧)方式 - 它似乎只是将失败的演员问题“更深”地转移到代码中。

10 个答案:

答案 0 :(得分:147)

使用“经典”方法,如果转换失败,则抛出异常。使用as方法,它会导致null,可以检查它,并避免抛出异常。

此外,您只能对引用类型使用“as”,因此如果要对值类型进行类型转换,则仍必须使用“经典”方法。

注意:

as方法只能用于可以分配null值的类型。这种用法仅表示引用类型,但是当.NET 2.0出现时,它引入了可空值类型的概念。由于可以为这些类型分配null值,因此它们可以与as运算符一起使用。

答案 1 :(得分:29)

空比较 MUCH 比抛出和捕获异常更快。例外有很大的开销 - 堆栈跟踪必须组装等。

异常应该表示意外状态,这通常不代表情况(as更好地工作时)。

答案 2 :(得分:25)

在某些情况下,处理null比处理异常更容易。特别是,合并算子很方便:

SomeClass someObject = (obj as SomeClass) ?? new SomeClass();

它还简化了您所在的代码(不使用多态性,并根据对象的类型进行分支):

ClassA a;
ClassB b;
if ((a = obj as ClassA) != null)
{
    // use a
}
else if ((b = obj as ClassB) != null)
{
    // use b
}

根据MSDN page的规定,as运算符相当于:

expression is type ? (type)expression : (type)null

避免了完全支持更快类型测试的异常,但也限制了它对支持null(引用类型和Nullable<T>)的类型的使用。

答案 3 :(得分:7)

as运算符在某些情况下很有用。

  1. 当您只需要知道某个对象属于特定类型但不需要专门对该类型的成员采取行动时
  2. 当您想避免例外而是明确处理null
  3. 您想知道对象之间是否存在CLR转换,而不仅仅是某些用户定义的转换。
  4. 第三点是微妙但重要的。在使用强制转换运算符的转换和使用as运算符成功的转换之间没有1-1映射。 as运算符严格限于CLR转换,不会考虑用户定义的转换(转换运算符)。

    具体而言,as运算符仅允许以下内容(来自C#lang规范的第7.9.11节)

    • 存在标识(第6.1.1节),隐式引用(第6.1.6节),装箱(第6.1.7节),显式引用(第6.2.4节)或拆箱(第6.2.5节)转换E到T的类型。
    • E或T的类型是开放式。
    • E是空文字。

答案 4 :(得分:3)

当您真正不知道变量可能是什么类型时,as关键字非常有用。如果您有一个函数将遵循不同的代码路径,具体取决于参数的实际类型,那么您有两个选择:

首先,使用普通演员:

if(myObj is string)
{
    string value = (string)myObj;

    ... do something
}
else if(myObj is MyClass)
{
    MyClass = (MyClass)myObj;
}

这要求您使用is检查对象的类型,这样您就不会尝试将其转换为失败的对象。这也有点多余,因为is - 类型检查在强制转换中再次完成(因此如果需要,它可以抛出异常)。

另一种方法是使用as

string myString = myObj as string;
MyClass myClass = myObj as MyClass;

if(myString != null)
{

}
else if(myClass != null)
{

}

这使得代码更短,并且还消除了冗余类型检查。

答案 5 :(得分:1)

如果不是有效的强制转换,则使用as将返回null,除了在try / catch中包装强制转换之外,还允许您执行其他操作。我讨厌经典演员。如果我不确定,我总是使用演员。另外,例外是昂贵的。空检查不是。

答案 6 :(得分:1)

我认为最好的“规则”只是在预期您的主题不是您要投放的对象时才使用'as'关键字:

var x = GiveMeSomething();

var subject = x as String;

if(subject != null)
{
  // do what you want with a string
}
else
{
  // do what you want with NOT a string
}

然而,当你的主题应该是你所投射的类型时,请使用'经典演员',就像你所说的那样。因为如果它不是你期望的类型,你将得到一个适合特殊情况的例外。

答案 7 :(得分:0)

这里没有什么深刻的发生。基本上,测试某些东西以确定它是否属于某种类型(即使用'as')是很方便的。您可能需要检查“as”调用的结果,以查看结果是否为空。

当您期望某个强制转换工作并且您希望抛出异常时,请使用“经典”方法。

答案 8 :(得分:0)

您使用“as”语句来避免出现异常的可能性,例如:你可以通过逻辑优雅地处理演员失败。只有在确定对象属于所需类型时才使用强制转换。我几乎总是使用“as”然后检查null。

答案 9 :(得分:0)

我认为如果将转换的结果传递给您知道将在不抛出ArgumentNullException之类的情况下处理空引用的方法,它会很有用。

我倾向于发现as的用处很少,因为:

obj as T

慢于:

if (obj is T)
    ...(T)obj...

使用as对我来说是一个非常边缘的场景,所以我想不出任何关于何时使用它而不仅仅是投射和处理(更具信息性)的投射异常的一般规则进一步上升。