我有一个安全投射对象的扩展方法,如下所示:
public static T SafeCastAs<T>(this object obj) {
if (obj == null)
return default(T);
// which one I should use?
// 1. IsAssignableFrom
if (typeof(T).IsAssignableFrom(obj.GetType()))
return (T)obj;
// 2. IsInstanceOfType
if (typeof(T).IsInstanceOfType(obj))
return (T) obj;
// 3. is operator
if (obj is T)
return (T) obj;
return default(T);
}
如您所见,我有3个选择,那么我应该使用哪一个?实际上IsAssignableFrom
,IsInstanceOfType
和is
运算符之间有什么区别?
答案 0 :(得分:51)
您可以使用您拥有的任何信息。
如果您要检查实例和静态类型,请使用is
。
如果您没有静态类型,那么您只有一个Type
对象,但是您有一个要检查的实例,请使用IsInstanceOfType
。
如果您没有实例,并且只想检查Type
的理论实例与另一个Type
的理论实例之间的兼容性,请使用IsAssignableFrom
。
但实际上你似乎只是在重新实现as operator(除了你的也可以用于非可空值类型,这通常不是一个很大的限制)。
答案 1 :(得分:10)
我猜你有效地实现了一个适用于值类型和引用类型的as
运算符的版本。
我会去:
public static T SafeCastAs<T>(this object obj)
{
return (obj is T) ? (T) obj : default(T);
}
IsAssignableFrom
适用于类型,is
适用于实例。他们会在你的情况下给你相同的结果,所以你应该使用最简单的版本恕我直言。
至于IsInstanceOfType
:这是以IsAssignableFrom
的形式实现的,因此没有区别。
您可以通过使用Reflector查看IsInstanceOfType()
:
public virtual bool IsInstanceOfType(object o)
{
if (o == null)
{
return false;
}
return this.IsAssignableFrom(o.GetType());
}
答案 2 :(得分:3)
我猜你应该选择“as”而不是自定义的“SafeCastAs”。但这只适用于类(不是结构),所以如果你想将这个方法用于结构,我也可以得到它。
运算符“is”基本上与Type.IsAssignableFrom相同,因此您只能保留“is”,它会检查您是否可以安全地将obj强制转换为T,没有异常。因此,它将涵盖您的方法中的先前检查。但是你应该知道它不会检查你是否可以将obj分配给T,因为用户定义了转换:explicit和implicit关键字。
答案 3 :(得分:0)
这些功能和操作符具有不同的含义。如果你有对象,你总是可以得到类型。所以你不会对你所拥有的东西开展工作,但你会做需要做的事情。
当您使用类层次结构时,差异非常明显。
请看以下示例
class ABase
{
}
class BSubclass : ABase
{
}
ABase aBaseObj = new ABase();
BSubclass bSubclassObj = new BSubclass();
ABase subObjInBaseRef = new BSubclass();
不同的操作会产生不同的结果。
typeof(ABase).IsInstanceOfType(aBaseObj) = True
typeof(ABase).IsInstanceOfType(bSubclassObj) = True
typeof(ABase).IsInstanceOfType(bSubclassObj) = True
typeof(BSubclass).IsInstanceOfType(aBaseObj) = False
bSubclassObj is ABase = True
aBaseObj is BSubclass = False
subObjInBaseRef is BSubclass = True
subObjInBaseRef is BSubclass = True
typeof(ABase).IsAssignableFrom(typeof(BSubclass)) = True
typeof(BSubclass).IsAssignableFrom(typeof(ABase))= False
如果没有等级,可能一切都是一样的。
但是,如果您使用层次结构,IsAssignableFrom
,是,IsInstanceOfType
会产生不同的结果。
可以尝试更多可能的组合。例如,您可以在此示例中引入与现有类无关的C类。