c#typeof应用于泛型参数超类型

use*_*597 4 c# generics wildcard typeof

我有一个方法,它没有任何T参数.

遗憾的是,如下所示,C#typeof运算符不适用于泛型.

public static string ToString(object obj)
{
    if (obj.GetType() == typeof(List<object>))
    {
        return "Bug: Never called";
    }
    if (obj.GetType() == typeof(List<int>))
    {
        return "Method only works for int lists";
    }
    return "";
}
Run Code Online (Sandbox Code Playgroud)

预期输出:ToString(整数列表)将返回"Bug:Never Called".

实际输出:"方法仅适用于int列表"

这在Java中运行得非常好.你会说c#中的泛型不支持这个.如何重构我的代码以使"ToString(object)"方法适用于对象列表?

要求:您不能修改方法的签名,只能修改它的实现.

不幸的是你不能让"int"类实现一个接口.因为int类是由Microsoft编写的.因此我无法在int类型上添加访问者模式.

das*_*ght 6

不幸的是,c#typeof运算符不适用于泛型,如下所示.

实际上,它非常幸运,它不能像你期望的那样工作.与Java不同,C#在运行时List<int>List<object>运行时之间进行区分,而不仅仅是在编译时.使用基本类型参​​数实例化的泛型的类型信息允许.NET通过避免类型擦除来生成更高效的代码.

如果您想测试对象是否是任何通用列表,请使用此检查:

var objT = obj.GetType();
if (objT.IsGenericType && objT.GetGenericTypeDefinition() == typeof(List<>)) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

因此,我不能在int类型上添加访问者模式.

C#为您提供了一种动态调度的强大机制,无需实现接口.例如,您可以这样做:

public static string ToString(object obj) {
    var list = obj as IList;
    if (list != null) {
        foreach (dynamic o in list) {
            Process(o);
        }
    }
}
static void Process(int n) { ... }
static void Process(string s) { ... }
static void Process(object o) { ... }
Run Code Online (Sandbox Code Playgroud)

以上将Process根据列表中对象的运行时类型选择正确的实现.