我为下面的通用代码创建了一个专门化:
public class BaseGeneric<T>
{
public static T DoStuff()
=> default;
}
public class SpecializedFromBaseGeneric : BaseGeneric<int>
{
public static new int DoStuff()
=> 789;
}
现在调用我想使用的
DoStuff()
方法var result = BaseGeneric<int>.DoStuff();
当我运行此代码时,
result
是0
而不是789
。调试器显示调用将从 DoStuff()
进入 public class BaseGeneric<T>
,而不是 SpecializedFromBaseGeneric
。
我做错了什么?
稍后编辑
我还尝试以以下格式创建专业化,但这甚至无法编译:
public class BaseGeneric<T> where T : int
{
public static T DoStuff()
=> 789;
}
我想做几个专业化,并使用类似于上面为
int
数据类型 BaseGeneric<int>.DoStuff()
指定的调用。对于每个专业化,都使用相同的语法,其中仅更改数据类型,但使用不同的实现(例如:对于字符串,将是 BaseGeneric<string>.DoStuff()
)。如何实现这种行为?
var result = BaseGeneric<int>.DoStuff()
这个调用了基类的函数。它返回 new T(),它等于 new int(),它等于零。
var result = SpecializedFromBaseGeneric.DoStuff()
这个会返回你所需要的。
public class BaseGeneric<T> where T : IConvertible
{
public static T DoStuff()
{
if (typeof(T) == typeof(int))
{
return (T)(object)789;
}
if (typeof(T) == typeof(string))
{
return (T)(object)"ss";
}
return default(T);
}
}
但是,正如这里的 asnwer 所暗示的那样,这很脆弱,并且不能涵盖所有可能的用法。
至于你想要做什么,据我所知,这种编译时多态性在 C# 中是不可能的。您必须在运行时解决专业化问题。
人们使用了多种技术,例如从 DI 容器中解析专业化,以防万一您在项目中使用了一种技术。
你可以看看 MediatR 是如何做的
最终,所有这些技术都归结为确定您想要在运行时专用的类型,并根据该类型创建专用泛型的实例。
查看这篇文章进行深入讨论:跨越泛型鸿沟。