c# - 如何检查类型是否永远不是有效的泛型参数?

标签 c# .net clr

我目前的代码如下,我想解决的是摆脱try-catch:

public static bool IsNeverValidGenericArgument(this Type type) {
    var elementType=type.GetElementType();

    if(null!=elementType) {
        if(type.IsArray)
            try {
                typeof(IList<>).MakeGenericType(elementType);
                return false;
            }
            catch(ArgumentException) {
            }
            catch(TypeLoadException) {
            }

        return true; // pointer or byref 
    }

    return
        typeof(void)==type||typeof(RuntimeArgumentHandle)==type
        ||
        typeof(ArgIterator)==type||typeof(TypedReference)==type;
}

我正在尝试编写动态类型构造的代码,我的代码将在每个传递的类型上调用 GetInterfaces(),但是消费者代码传递的某些类型可能会导致内部 RuntimeType 中的 TypeLoadException(例如 3.5 中的 typeof(ArgIterator).MakeArrayType().MakeArrayType(),但不是 4.0+),我需要首先检查它是否永远不是有效的通用参数。 try-catch 有效,但效果不佳。

请注意,它抛出的情况可能因 .Net 框架的不同版本而异


编辑:

该方法的替代版本是:

public static bool IsNeverValidGenericArgument(this Type type) {
    var elementType=type.GetElementType();

    if(null!=elementType) {
        if(type.IsArray)
            return elementType.IsNeverValidGenericArgument();

        return true; // pointer or byref 
    }

    return
        typeof(void)==type||typeof(RuntimeArgumentHandle)==type
        ||
        typeof(ArgIterator)==type||typeof(TypedReference)==type;
}

但这会将一些类型报告为无效,实际上这将不会导致 RuntimeType 中的异常,例如 typeof(ArgIterator).MakeArrayType(2) .MakeArrayType()

我知道有些类型通常不被使用,但我无法避免在消费者代码中使用它们。

最佳答案

当您尝试使用 typeof(ArgIterator).MakeArrayType().MakeArrayType() 参数构造泛型类型时,它是引发异常的内部 native CLR 代码。从该事实中得出的最重要的结论是,抛出的是 CLR 实现细节,而不是确定泛型类型参数有效性的标准或公开 API 的一部分。这意味着没有好的方法可以确定是否可以在不实际尝试的情况下构造泛型。 编辑:这也意味着没有好的方法来确定某些东西是否适用于特定版本的 CLR 而不适用于其他版本。

但是,更重要的是,如果您尝试构造一个带有无效参数的泛型类型,那确实是一种异常(exception)情况,正确的做法是抛出异常。我不能说你的代码做了什么,但如果你担心你的消费者使用导致 TypeLoadException 被抛出的类调用它,也许你应该让这些错误冒出来,这样消费者知道有问题。

TL;DR:您可能不应该做任何您想做的事情来处理异常情况。就让它扔吧。

关于c# - 如何检查类型是否永远不是有效的泛型参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18078395/

相关文章:

.net - 使用 monotorrent : How do I add webseeds? 创建一个 torrent 文件

c# - Windows 窗体是否有任何开源或免费的图形/报告/图表框架?

c# - 是否可以读取实习生池中的所有字符串?

c# - 使用 SQL 具有不同日期的复合条目

C# (MSIL) 到 native X86 代码?

c# - .NET 中的 Erlang 风格的轻量级进程

c# - 使用EntityObjects与Ajax绑定(bind)的Telerik MVC网格获取“循环引用”异常

.net - 当问题有新答案时,网站如何发送电子邮件

c++-cli - 如何将 array<unsigned char> 转换为 unsigned char[]?

c# - C# 7.0 中通过引用返回的值是存储在堆栈中还是堆中?