C#类型推理:如何正确定义方法上的约束
本文关键字:方法 约束 定义 何正确 类型 推理 | 更新日期: 2023-09-27 18:20:19
嗨,我很难让C#类型推理按我的意愿进行。我有一个非常具体的情况,我有很多风格的变量
ConcurrentDictionary<T, IDictionary<U, V> >
其中,T、U、V可以是一些随机类型,如long、int或其他类型。
我想写一个能处理这类变量的方法——尤其是检查它们的直方图。
所以我写了一个方法
public static IOrderedEnumerable<Tuple<int,int>> GetDictionaryHistogram<T, U, V, W>(T dictionary) where T : ConcurrentDictionary<U, IDictionary<V, W>>
{
return dictionary.Select(p => p.Value.Count)
.GroupBy(p => p)
.Select(p => new Tuple<int, int>(p.Key, p.Count()))
.OrderBy(p => p.Item1);
}
但是当我尝试调用它时,C#给了我一个错误,它无法推断类型。例如类型的变量
ConcurrentDictionary<int,IDictionary<int, int> > foo;
我得到错误:
错误118方法的类型参数"Auditor.AuditorHelpers.GetDictionaryHistogram(T)"不能为根据用法推断。请尝试显式指定类型参数。
我做错了什么?
类型推断从参数到形式参数类型。从未对约束进行过推断,因为约束不是方法的签名的一部分。
在您的情况下,类型推理必须始终失败;类型推断不可能推断U和V的类型,因为它们不出现在形式参数类型中。
大约有十几个人告诉我,我错误地认为这条规则是合理的,请参阅我关于这个主题的文章的评论。
类型参数T
是不必要的。你应该只写
public static IOrderedEnumerable<Tuple<int,int>> GetDictionaryHistogram<U, V, W>(
ConcurrentDictionary<U, IDictionary<V, W>> dictionary)
它应该可以正常工作。
您的约束类型(其中参数必须是特定类型)仅在少数情况下有用。最常见的是避免对实现接口的值类型进行装箱。比较这两种方法:
public static DoSomething(ISomeInterface thing) {}
public static DoSomething<T>(T thing) where T : ISomeInterface {}
当使用值类型参数调用第一个方法时,该参数将被装箱并强制转换为接口类型。
当使用值类型调用第二个方法时,泛型类型参数将替换为值类型,并且不会进行装箱。
我认为编译器说它无法计算出类型之间的依赖关系。
尝试做:
public static IOrderedEnumerable<Tuple<int,int>> GetDictionaryHistogram<U, V, W>(ConcurrentDictionary<U, IDictionary<V, W>> dictionary)
{
return dictionary.Select(p => p.Value.Count)
.GroupBy(p => p)
.Select(p => new Tuple<int, int>(p.Key, p.Count()))
.OrderBy(p => p.Item1);
}