繁体   English   中英

类不是从对象继承的?

[英]Class not inheriting from object?

我正在研究一种方法,该方法使用反射来检查参数类型的方法。 这个方法遍历ParameterInfo,并且正在对这些参数的类型做些什么。

我总是假设如果TypeInfo.IsClasstrue ,那么这个类型是一个类,并且总是从类型object派生(间接)(当然,当类型是object本身时)。 因此,如果TypeInfo.IsClass为true,则必须设置TypeInfo.BaseType

我的假设是错的! 有些类不是从类型object派生的。 我的假设搞砸了我的代码。

例如:

Type type = typeof(int).MakeByRefType();

type.IsClasstruetype.BaseTypenull

如果你考虑一下,这是合乎逻辑的。 我可以通过检查TypeInfo.IsByRef来防止我的代码崩溃。

现在我的问题是:是否有更多这样的“异国情调”类型(除了ByRef类型和类型object ),它们是一个类( IsClass == true )但没有基类型( BaseType == null )?

在回答之前:我只是IsClass == true类型! 我的int类型示例只是一个例子。 它可以是任何类型。 所以请不要:

  • 接口
  • 结构
  • 空虚

答案到目前为止:

  • ByRef类型( T& ):如问题中所述。
  • 指针类型( T* ):由Mark Gravell发现。

我会说IsClass在这里只是误导。 它指出:

获取一个值,该值指示System.Type是否为类; 也就是说,不是值类型或接口。

它以这种方式实现 :它检查标志是否包含Interface ,以及它是否是ValueType

不幸的是,还有更多的事情。 指针不是托管类型 by-ref与指针非常相似。 指针不是object ,虽然通常使用强制转换实际上是取消引用/强制转换。 这同样适用于诸如int*类的直接指针之类的东西。

并非.NET中的所有内容都是object :)

var baseType = typeof(int*).BaseType; // null
bool liesAndMoreLies = typeof(int*).IsClass; // true

Eric Lippert在这里更多地介绍了这一点:并非所有内容都来自于对象 - 并列出了一些其他示例(例如,开放泛型类型)。

除了没有实例化的泛型类型,用链接指出并非一切都来自于对象@Lippert先生的博客 Gravell先生的好答案 ,我建议找到满足您要求的其他类型可以由您自己完成。

现在,让我们从头开始解决这个问题。 首先,您要弄清楚的类型应该在核心运行时库中,哪个是mscorlib.dll

public static partial class MartinMulderExtensions {
    public static IEnumerable<Type> GetMscorlibTypes() {
        return
            from assembly in AppDomain.CurrentDomain.GetAssemblies()
            let name=assembly.ManifestModule.Name
            where 0==String.Compare("mscorlib.dll", name, true)
            from type in assembly.GetTypes()
            select type;
    }
}

然后,类型具有MakeXXXXType()方法,例如MakeByRefType() 在这里,我们考虑更多的可能性,即任何返回一种或多种类型的方法 由于我们对任意类型的参数没有任何了解,因此我们认为方法采用零参数

partial class MartinMulderExtensions {
    public static IEnumerable<Type> GetRetrievableTypes(this Type type) {
        var typesArray=(
            from method in type.GetMethods()
            where 0==method.GetParameters().Count()

            let typeArray=
                method.InvokeZeroArgumentMethodWhichReturnsTypeOrTypes(type)

            where null!=typeArray
            select typeArray).ToArray();

        var types=
            typesArray.Length>0
                ?typesArray.Aggregate(Enumerable.Union)
                :Type.EmptyTypes;

        return types.Union(new[] { type });
    }
}

但是,对于InvokeZeroArgumentMethodWhichReturnsTypeOrTypes的实现,有几种这种调用的无效情况,例如在非泛型类型上调用GetGenericParameterConstraints() ; 我们通过try-catch避免这些情况:

partial class MartinMulderExtensions {
    public static IEnumerable<Type>
        InvokeZeroArgumentMethodWhichReturnsTypeOrTypes(
        this MethodInfo method, Type t
        ) {
        try {
            if(typeof(Type)==method.ReturnType) {
                var type=method.Invoke(t, null) as Type;

                if(null!=type)
                    return new[] { type };
            }

            if(typeof(Type[])==method.ReturnType) {
                var types=method.Invoke(t, null) as Type[];

                if(types.Length>0)
                    return types;
            }
        }
        catch(InvalidOperationException) {
        }
        catch(TargetInvocationException) {
        }
        catch(TargetException) {
        }

        return Type.EmptyTypes;
    }
}

现在,找出所需的类型。 让我们一步一步地构建方法。 第一步是定义所有可能类型的范围:

partial class MartinMulderExtensions {
    public static Type[] GetDesiredTypes() {
        return (
            from type in MartinMulderExtensions.GetMscorlibTypes()
            .Select(x => x.GetRetrievableTypes())
            .Aggregate(Enumerable.Union)

然后,根据你所说的基本:

现在我的问题是:是否有更多这样的“异国情调”类型(除了ByRef类型和类型object ),它们是一个类( IsClass == true )但没有基类型( BaseType == null )?

            where null==type.BaseType
            where type.IsClass

您还说before answer

在回答之前:我只是IsClass == true类型! 我的int类型示例只是一个例子。 它可以是任何类型。 所以请不要:

  • 接口
  • 结构
  • 空虚
            where !type.IsInterface
            where !type.IsValueType
            where typeof(void)!=type

最后一步,让我们跳过已经回答并完成方法:

            where !type.IsByRef
            where !type.IsPointer
            select type
            ).ToArray();
    }
}

现在,您可以调用MartinMulderExtensions.GetDesiredTypes()来获取所需的类型:

public partial class TestClass {
    public static void TestMethod() {
        foreach(var type in MartinMulderExtensions.GetDesiredTypes())
            Console.WriteLine(type);
    }
}

完整代码:

public static partial class MartinMulderExtensions {
    public static IEnumerable<Type> GetMscorlibTypes() {
        return
            from assembly in AppDomain.CurrentDomain.GetAssemblies()
            let name=assembly.ManifestModule.Name
            where 0==String.Compare("mscorlib.dll", name, true)
            from type in assembly.GetTypes()
            select type;
    }

    public static IEnumerable<Type>
        InvokeZeroArgumentMethodWhichReturnsTypeOrTypes(
        this MethodInfo method, Type t
        ) {
        try {
            if(typeof(Type)==method.ReturnType) {
                var type=method.Invoke(t, null) as Type;

                if(null!=type)
                    return new[] { type };
            }

            if(typeof(Type[])==method.ReturnType) {
                var types=method.Invoke(t, null) as Type[];

                if(types.Length>0)
                    return types;
            }
        }
        catch(InvalidOperationException) {
        }
        catch(TargetInvocationException) {
        }
        catch(TargetException) {
        }

        return Type.EmptyTypes;
    }

    public static IEnumerable<Type> GetRetrievableTypes(this Type type) {
        var typesArray=(
            from method in type.GetMethods()
            where 0==method.GetParameters().Count()

            let typeArray=
                method.InvokeZeroArgumentMethodWhichReturnsTypeOrTypes(type)

            where null!=typeArray
            select typeArray).ToArray();

        var types=
            typesArray.Length>0
                ?typesArray.Aggregate(Enumerable.Union)
                :Type.EmptyTypes;

        return types.Union(new[] { type });
    }

    public static Type[] GetDesiredTypes() {
        return (
            from type in MartinMulderExtensions.GetMscorlibTypes()
            .Select(x => x.GetRetrievableTypes())
            .Aggregate(Enumerable.Union)

            where null==type.BaseType
            where type.IsClass
            where !type.IsInterface
            where !type.IsValueType
            where typeof(void)!=type

            where !type.IsByRef
            where !type.IsPointer

            select type
            ).ToArray();
    }
}

Type.GetElementType方法(来自MSDN)

当前数组,指针或引用类型包含或引用的对象类型,如果当前Type不是数组或指针,或者不通过引用传递,或者表示泛型类型或类型参数,则返回null在泛型类型或通用方法的定义中。

码...

Type type = typeof(int).MakeByRefType();
bool isClass = type.IsClass; // true

Type elementType = type.GetElementType(); // Int32
Type baseType = elementType.BaseType; // ValueType

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM