您好我很难做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)'不能 从用法推断。尝试明确指定类型参数。
我做错了什么?
答案 0 :(得分:7)
类型推断从参数推断到形式参数类型。没有对约束进行推断,因为约束不是方法的签名的一部分。
在您的情况下,类型推断必须始终失败;类型推断不可能推断出U和V的类型,因为它们不会出现在形式参数类型中。
有十几个人告诉我,我认为这个规则是明智的是错的,请参阅my article on the subject的评论。
答案 1 :(得分:2)
类型参数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 {}
当使用值类型参数调用第一个方法时,参数将被装箱并转换为接口类型。
当使用值类型调用第二个方法时,泛型类型参数将替换为值类型,并且不会发生装箱。
答案 2 :(得分:1)
我认为编译器说它无法弄清楚你的类型之间的依赖关系。
尝试做:
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);
}