来自文档:
as运算符就像一个转换器,除了它在转换失败时产生null而不是引发异常。更正式地说,表达形式:
expression as type
相当于:
expression is type ? (type)expression : (type) null
除了表达式只被评估一次。
那你为什么不选择以某种方式做到这一点。为什么有两个铸造系统?
答案 0 :(得分:80)
它们不是两个铸造系统。两者有类似的行为,但意义却截然不同。 “as”表示“我认为这个对象可能实际上属于另一种类型;如果不是,则给我null。”演员表示两件事之一:
我确信这个对象实际上是另一种类型。这样做,如果我错了,请崩溃程序。
我确信这个对象不属于其他类型,但是有一种众所周知的方法可以将当前类型的值转换为所需类型。 (例如,将int转换为short。)实现它,如果转换实际上不起作用,则使程序崩溃。
有关详细信息,请参阅我关于此主题的文章。
答案 1 :(得分:12)
效率和效果
执行演员表演的一部分是一些综合类型检查;因此,使用显式类型检查为实际强制转换添加前缀是多余的(类型检查会发生两次)。使用as
关键字可确保只执行一次类型检查。您可能会想“但它必须执行空检查而不是第二次类型检查”,但与类型检查相比,空检查非常有效且高效。
if (x is SomeType )
{
SomeType y = (SomeType )x;
// Do something
}
进行2次检查,而
SomeType y = x as SomeType;
if (y != null)
{
// Do something
}
生成1x - 与类型检查相比,空检查非常便宜。
答案 2 :(得分:11)
因为如果你不能像你期望的那样进行投射,有时候你会想要失败,有时候你不在乎,如果它不能投射,只想丢弃给定的对象。
它基本上是一个包含在try块中的常规强制转换的更快版本;但是As
更具可读性,也可以节省打字。
答案 3 :(得分:7)
它允许快速检查而不需要尝试/转换开销,在某些情况下可能需要处理基于消息的继承树。
我经常使用它(收到消息,对特定的子类型做出反应)。尝试/施放wouuld要慢得多(每条消息都经过多次尝试/捕获帧) - 我们谈到在这里每秒处理200.000条消息。
答案 4 :(得分:2)
我通常根据代码的语义选择一个或另一个。
例如,如果您知道某个object
必须是string
,那么请使用(string)
,因为这表示编写代码的人确定该对象是一个string
,如果它不是我们已经有比抛出的运行时强制转换异常更大的问题。
如果您不确定该对象是否属于特定类型但想要具有何时具有逻辑,请使用as
。您可以使用is
运算符,然后使用强制转换,但as
运算符效率更高。
答案 5 :(得分:2)
让我给你一个真实世界的场景,你可以在哪里使用它们。
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;
}
}
答案 6 :(得分:0)
也许例子会有所帮助:
// 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
}