c# - 从 C# 中的泛型方法调用非泛型方法
问题描述
这类似于从泛型方法调用重载泛型方法这个问题,但它不一样:在这种情况下,方法返回void
,而我需要返回泛型类型T
,所以建议的解决方案不起作用。
我正在实现一个类似元组的类,它具有这些参数的通用参数和访问器:
public class MyClass<T1, T2>
{
private readonly T1 _item1;
private readonly T2 _item2;
public MyClass(T1 item1, T2 item2)
{
_item1 = item1;
_item2 = item2;
}
public T1 GetItem(T1 _) => _item1;
public T2 GetItem(T2 _) => _item2;
private T GetItem<T>(T x)
{
throw new ArgumentException();
// return x;
}
public T Get<T>()
{
return GetItem(default(T));
}
}
我想像这样使用这个类:
var obj = new MyClass<int, string>(1, "hello");
var a = obj.Get<int>();
var b = obj.Get<string>();
但是如果我尝试这个,T GetItem<T>(T x)
总是调用泛型(抛出异常),而不是非泛型实现。
如果我尝试GetItem
直接访问该方法,它会按预期工作:
var obj = new MyClass<int, string>(1, "hello");
var q = obj.GetItem(default(int));
var w = obj.GetItem(default(string));
q
并按预期w
包含1
和。hello
有没有办法让我随心所欲地使用这个类(使用obj.Get<T>
)?我想避免Item1
Item2
Item3
吸气剂。
解决方案
但是如果我尝试这个,
T GetItem<T>(T x)
总是调用泛型(抛出异常),而不是非泛型实现。
那是因为重载决议发生在编译时,而在编译时,具体类型T
是未知的。
有没有办法让我随心所欲地使用这个类(使用
obj.Get<T>
)?
使用普通的旧动态类型检查,确保:
public class MyClass<T1, T2>
{
private readonly T1 _item1;
private readonly T2 _item2;
public MyClass(T1 item1, T2 item2)
{
_item1 = item1;
_item2 = item2;
}
public T Get<T>()
{
if (typeof(T) == typeof(T1))
{
return (T)(object)_item1;
}
if (typeof(T) == typeof(T2))
{
return (T)(object)_item2;
}
throw new InvalidOperationException();
}
}
此解决方案的优点是边缘情况(T1 == T2,或 T 既不匹配 T1 也不匹配 T2)的行为被正确定义并且易于查看。
或者,您可以使用链接到的问题中使用的dynamic
“hack”,您只需将结果转换为T
: return (T)GetItem((dynamic)default(T));
,这是一个工作小提琴。
但这只是丑陋的,请不要这样做。将小提琴与上面的版本进行比较,并诚实地判断哪一个更易于阅读、更易于理解,因此更易于维护。
推荐阅读
- angularjs - 使用带有模板 url 的 ui 路由器时获得“转换拒绝”
- ios - 我可以将`willConnectTo`用作iOS中单窗口应用程序的`didFinishLaunching`吗?
- python - 从 Flask 路由内的子进程运行“pip install pkg --upgrade”是否会使新模块在同一路由/实例中可用?
- c++ - 使用 argc 和 argv 参数写入和读取特定文件
- windows-7 - 这些是什么“←[
“ Deno 打印到控制台的东西? - python - pytest:处理退出的 C 扩展
- c++ - 没有函数模板的实例
- python - 使用 PyPy 作为 PyCharm 的解释器
- java - 了解递归函数
- flutter - 我想导入网页的一部分