泛型:为什么编译器在这种情况下不能推断出类型参数?

Ani*_*Ani 8 c# generics type-inference

我想写一个扩展方法,它可以在字典上工作,它的值是某种顺序.不幸的是,编译器似乎无法从我对该方法的使用中推断出泛型参数; 我需要明确指定它们.

public static void SomeMethod<TKey, TUnderlyingValue, TValue>
    (this IDictionary<TKey, TValue> dict)
    where TValue : IEnumerable<TUnderlyingValue> { }    

static void Usage()
{
    var dict = new Dictionary<int, string[]>();
    var dict2 = new Dictionary<int, IEnumerable<string>>();

    //These don't compile
    dict.SomeMethod();
    SomeMethod(dict); // doesn't have anything to do with extension-methods
    dict2.SomeMethod(); // hoped this would be easier to infer but no joy


    //These work fine
    dict.SomeMethod<int, string, string[]>();
    dict2.SomeMethod<int, string, IEnumerable<string>>();
}
Run Code Online (Sandbox Code Playgroud)

我意识到类型推断不是一门精确的科学,但我想知道是否有一些基本的"规则"我在这里缺失 - 我不熟悉规范的细节.

  1. 这是推理过程的缺点还是我期望编译器在这种情况下应该"弄明白"不合理(或许是歧义)?
  2. 我可以改变方法的签名,使其同样功能但"可推断"吗?

Eri*_*ert 15

我意识到类型推断不是一门精确的科学

我不确定我是否同意.规范非常详细.

我想知道这里是否有一些基本的"规则"

您缺少的基本规则可能是约束不是签名的一部分.类型推断起作用于签名.

我认为这个设计决定的理由很充分.然而,许多人认为我认为有充分的理由做出设计决定,这在道德上是错误的.如果你有兴趣阅读关于我是对还是错的主题的几百万字,请看我关于这个主题的文章和一百多条评论告诉我我错了:

http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx

这是推理过程的缺点吗?

可以说是的.在我看来,根据竞争设计要求,这是一个合理的选择.(那些"做用户意味着什么"和"当事情看起来模棱两可时给出错误".)

我希望编译器在这种情况下应该"弄明白"不合理吗?

不,你看起来像个合理的人,你的期望似乎是基于良好的推理.然而,完全有可能有一个合理的期望,但仍未得到满足.这将是其中一个案例.

我可以改变方法的签名,使其同样功能但"可推断"吗?

这将是困难的,因为通用的Dictionary类型在其转换中不是协变的或逆变的.您想要捕获的概念不容易在类型系统中以提供推理的方式表达.

如果您更喜欢使用具有更高级类型推断的语言,请考虑使用F#.如果您更喜欢倾向于"做用户意味着什么"而不是"报告模糊错误"的语言,请考虑使用VB.

  • @Joan:我们没有名字.这是整个C#设计委员会的共同努力.尤其是Anders,Mads和我在这方面做了大量工作.Erik Meijer和一些Microsoft研究团队成员也提供了许多有用的想法,特别是在如何解决循环情况方面.我不记得谁在专利声明中. (4认同)