我有一个方法,它没有任何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 "";
}
预期输出:ToString(整数列表)将返回“Bug:Never Called”。
实际输出:“方法仅适用于int列表”
这在Java中完美无缺。你会说c#中的泛型不支持这个。如何重构我的代码以使“ToString(object)”方法适用于对象列表?
要求:您不能修改方法的签名,只能修改它的实现。
不幸的是你不能让“int”类实现一个接口。因为int类是由Microsoft编写的。因此,我无法在int类型上添加访问者模式。
答案 0 :(得分:6)
不幸的是,c#typeof运算符并不适用于泛型,如下所示。
实际上,很幸运的是,它并不像你期望的那样有效。与Java不同,C#在运行时区分List<int>
和List<object>
,而不仅仅是在编译时。使用基本类型参数实例化的泛型的类型信息允许.NET通过避免类型擦除来生成更高效的代码。
如果您想测试对象是否是任何通用列表,请改用此检查:
var objT = obj.GetType();
if (objT.IsGenericType && objT.GetGenericTypeDefinition() == typeof(List<>)) {
...
}
因此我无法在
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) { ... }
以上将根据列表中对象的运行时类型选择正确的Process
实现。