47

我有一个安全转换对象的扩展方法,如下所示:

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, 和isoperator之间有什么区别?

4

4 回答 4

68

您可以使用您拥有的任何信息。

如果您有要检查的实例和静态类型,请使用is.

如果您没有静态类型,那么您只有一个Type对象,但您有一个要检查的实例,请使用IsInstanceOfType.

如果您没有实例,并且只想检查 a 的理论实例Type与 another之间的兼容性Type,请使用IsAssignableFrom.

但实际上似乎您只是在重新实现as 运算符(除了您的运算符也适用于不可为空的值类型,这通常不是一个很大的限制)。

于 2013-04-06T16:26:48.497 回答
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());
}
于 2013-04-06T16:25:34.137 回答
3

我想您应该只使用“ as ”而不是您的自定义“SafeCastAs”。但这仅适用于类(不适用于结构),因此如果您也想将此方法用于结构,我可以得到它。

运算符“is”基本上与 Type.IsAssignableFrom 相同,因此您只能保留“is”,它检查是否可以安全地将 obj 转换为 T,没有例外。因此,它将涵盖您方法中先前的两项检查。但是您应该知道,由于用户定义的转换:显式隐式关键字,它不会检查您是否可以将 obj 分配给 T。

于 2013-04-06T16:38:51.117 回答
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, is ,并IsInstanceOfType产生不同的结果。

还有更多可能的组合可以尝试。例如,您可以在此示例中引入一个与现有类无关的类 C。

于 2017-08-14T11:12:36.240 回答