如果你想在大多数时候想要改变类型,你只想使用传统的演员表。
var value = (string)dictionary[key];
这很好,因为:
那么使用as
的好例子是什么?我无法真正找到或想到适合它的东西?
注意:实际上我认为有时候编译器会阻止在as
工作的情况下使用强制转换(泛型相关?)。
答案 0 :(得分:28)
当<{1>} 有效时,如果对象不属于您想要的类型,则使用as
,如果是,则需要采取不同的行动。例如,在某些伪代码中:
foreach (Control control in foo)
{
// Do something with every control...
ContainerControl container = control as ContainerControl;
if (container != null)
{
ApplyToChildren(container);
}
}
或LINQ to Objects中的优化(很多这样的例子):
public static int Count<T>(this IEnumerable<T> source)
{
IList list = source as IList;
if (list != null)
{
return list.Count;
}
IList<T> genericList = source as IList<T>;
if (genericList != null)
{
return genericList.Count;
}
// Okay, we'll do things the slow way...
int result = 0;
using (var iterator = source.GetEnumerator())
{
while (iterator.MoveNext())
{
result++;
}
}
return result;
}
所以使用as
就像is
+演员一样。根据以上示例,几乎总是随后使用无效检查。
答案 1 :(得分:14)
每当您需要安全施放对象时,请使用as
:
MyType a = (MyType)myObj; // throws an exception if type wrong
MyType a = myObj as MyType; // return null if type wrong
答案 2 :(得分:8)
用于避免双重投射逻辑,如:
if (x is MyClass)
{
MyClass y = (MyClass)x;
}
使用
MyClass y = x as MyClass;
if (y == null)
{
}
仅供参考,为案例#1生成的IL:
// if (x is MyClass)
IL_0008: isinst MyClass
IL_000d: ldnull
IL_000e: cgt.un
IL_0010: ldc.i4.0
IL_0011: ceq
IL_0013: stloc.2
IL_0014: ldloc.2
IL_0015: brtrue.s IL_0020
IL_0017: nop
// MyClass y = (MyClass)x;
IL_0018: ldloc.0
IL_0019: castclass MyClass
IL_001e: stloc.1
和案例#2:
// MyClass y = x as MyClass;
IL_0008: isinst MyClass
IL_000d: stloc.1
// if (y == null)
IL_000e: ldloc.1
IL_000f: ldnull
IL_0010: ceq
IL_0012: stloc.2
IL_0013: ldloc.2
IL_0014: brtrue.s IL_0018
答案 3 :(得分:5)
使用as
不会抛出强制转换异常,但如果强制转换失败则只返回null
。
答案 4 :(得分:2)
Enumerable中.Count()的实现使用它来使Collection()更快地收集
实施如下:
ICollection<TSource> collection = source as ICollection<TSource>;
if (collection != null)
{
return collection.Count;
}
ICollection collection2 = source as ICollection;
if (collection2 != null)
{
return collection2.Count;
}
尝试将源转换为ICollection或ICollection都具有Count属性。
如果失败则Count()迭代整个源。
因此,如果您不确定类型并且之后需要该类型的对象(如上例所示),则应使用as
。
如果您只想测试对象是否属于给定类型,请使用is
,如果您确定该对象属于给定类型(或派生自/实现该类型),那么您可以< / p>
答案 5 :(得分:1)
好的回复所有人,但让我们有点实用。在您自己的代码中,即非供应商代码,AS关键字的REAL功能不会脱颖而出。
但是当在WPF / silverlight中处理供应商对象时,AS关键字是一个真正的奖励。 例如,如果我在Canvas上有一系列控件并且我想跟踪thelast selectedControl,但是当我点击Canvas时清除跟踪变量我会这样做:
private void layoutroot_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
//clear the auto selected control
if (this.SelectedControl != null
&& sender is Canvas && e.OriginalSource is Canvas)
{
if ((sender as Canvas).Equals(( e.OriginalSource as Canvas)))
{
this.SelectedControl = null;
}
}
}
它使用AS keyoword的另一个原因是当你的Class实现了一个或多个接口并且你想明确地只使用一个接口时:
IMySecond obj = new MyClass as IMySecond
虽然这里不是真的有必要,如果MyClass没有实现IMySecond,它会给变量obj赋值null
答案 6 :(得分:0)
以下是http://blog.nerdbank.net/2008/06/when-not-to-use-c-keyword.html
的摘录class SomeType {
int someField;
// The numeric suffixes on these methods are only added for reference later
public override bool Equals1(object obj) {
SomeType other = obj as SomeType;
if (other == null) return false;
return someField == other.SomeField;
}
public override bool Equals2(object obj) {
if (obj == null) return false;
// protect against an InvalidCastException
if (!(obj is SomeType)) return false;
SomeType other = (SomeType)obj;
return someField == other.SomeField;
}
}
上面的Equals1方法比Equals2更有效(也更容易阅读),尽管它们可以完成相同的工作。虽然Equals1编译为执行类型检查的IL并且只执行一次,但Equals2首先编译为“is”运算符进行类型比较,然后进行类型比较并作为()运算符的一部分进行转换。因此,在这种情况下使用“as”实际上更有效。它更容易阅读的事实是一个奖励。
总之,只使用C#“as”关键字,在非特殊情况下,您希望转换失败。如果你指望一个强制转换成功并且没有准备接收任何失败的对象,你应该使用()强制转换运算符,以便抛出适当且有用的异常。