我知道当您使用这样的显式转换时:
(someType)someobject
如果someobject
不是真的,你会得到一个无效的强制转换异常someType
。
我也明白,当你as
这样投射时:
myObject = someObject as someType
myObject
null
如果someObject
is not really则仅渲染someType
。
这些评估有何不同,为什么?
John Skeet 有一个C# 常见问题解答,他解释了两个运算符之间的差异。请参阅段落“使用强制转换语法和 as 运算符有什么区别?”。
引用 :
使用 as 运算符在三个重要方面不同于 C# 中的强制转换:
- 当您尝试转换的变量不是请求的类型或在其继承链中时,它返回 null,而不是引发异常。
- 它只能应用于转换为引用类型的引用类型变量。
- 使用 as 不会执行用户定义的转换,例如隐式或显式转换运算符,而强制转换语法将执行此操作。
实际上,在 IL 中定义了两种完全不同的操作来处理这两个关键字(castclass 和 isinst 指令)——这不仅仅是 C# 编写的“语法糖”来获得这种不同的行为。与强制转换相比,Microsoft CLR 的 v1.0 和 v1.1 中的 as 运算符似乎稍快一些(即使在没有由于异常而严重降低强制转换性能的无效强制转换的情况下)。
多年过去了......但几分钟前,我遇到了一个我认为值得注意的实际例子 - 两者之间的区别:
看一下这个:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(GenericCaster<string>(12345));
Console.WriteLine(GenericCaster<object>(new { a = 100, b = "string" }) ?? "null");
Console.WriteLine(GenericCaster<double>(20.4));
//prints:
//12345
//null
//20.4
Console.WriteLine(GenericCaster2<string>(12345));
Console.WriteLine(GenericCaster2<object>(new { a = 100, b = "string" }) ?? "null");
//will not compile -> 20.4 does not comply due to the type constraint "T : class"
//Console.WriteLine(GenericCaster2<double>(20.4));
/*
* Bottom line: GenericCaster2 will not work with struct types. GenericCaster will.
*/
}
static T GenericCaster<T>(object value, T defaultValue = default(T))
{
T castedValue;
try
{
castedValue = (T) Convert.ChangeType(value, typeof(T));
}
catch (Exception)
{
castedValue = defaultValue;
}
return castedValue;
}
static T GenericCaster2<T>(object value, T defaultValue = default(T)) where T : class
{
T castedValue;
try
{
castedValue = Convert.ChangeType(value, typeof(T)) as T;
}
catch (Exception)
{
castedValue = defaultValue;
}
return castedValue;
}
}
底线: GenericCaster2 不适用于结构类型。GenericCaster 将。