C# 为什么编译器不能为我推断类型?(又称聪明人聪明可数)

C# 为什么编译器不能为我推断类型?(又称聪明人聪明可数),c#,generics,C#,Generics,我用的是乔恩·斯基特非常聪明的。如果你还没看过,我建议你去看看 该类定义如下: public class SmartEnumerable<T> : IEnumerable<SmartEnumerable<T>.Entry> 但是,这给了我一个编译器错误: 方法的类型参数 'MiscUtil.Collections.SmartEnumerable.SmartEnumerable(System.Collections.Generic.IEnumerable)'

我用的是乔恩·斯基特非常聪明的。如果你还没看过,我建议你去看看

该类定义如下:

public class SmartEnumerable<T> : IEnumerable<SmartEnumerable<T>.Entry>
但是,这给了我一个编译器错误:

方法的类型参数 'MiscUtil.Collections.SmartEnumerable.SmartEnumerable(System.Collections.Generic.IEnumerable)' 无法从用法推断。尝试 指定类型参数 明确地说

我不清楚这到底是为什么。有什么办法吗。为什么它看不到我在使用
IEnumerable
并从中推断出来呢。我可以更改任何内容以使其识别我正在使用的类型吗

我真的很想用某种方法来构造一个SmartEnumerable,而不必指定类型——因为我主要是在ASP.NET MVC的UI中使用它,在这里,我并不总是使用
包含
类型,而是依赖
var
来获取引用。我最终不得不包含类型,以便能够使用SmartEnumerable,这降低了它的优雅性

哦,我本来可以直接给约翰发电子邮件,但他可能会在这里更快地回复:-)


双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟双向飞碟

public static class SmartEnumerable {
  public static SmartEnumerable<T> Create<T>(IEnumerable<T> source) {
    return new SmartEnumerable<T>(source);
  }
}

void Example() {
  IEnumerable<string> myCats = GetMyCats();
  var se = SmartEnumerable.Create(myCats);
}
可计算的公共静态类{
公共静态可数创建(IEnumerable源){
返回新的智能数字(源);
}
}
void示例(){
IEnumerable myCats=GetMyCats();
var se=智能可数。创建(myCats);
}
您的代码失败,因为C#无法推断构造函数上的泛型参数。但C#完全能够推断其他方法的通用参数


在C#中,拥有一个名称仅因泛型参数不同的类是完全合法的。例如,Foo和Foo(在引擎盖下,它们实际上是不同的名称)。因此,上述示例适用于大多数场景。我个人在定义泛型类时使用它,在泛型类中构造函数使用足够的参数来推断完整类型。

我同意JaredPar的观点。我想指出的是,您还可以使用扩展方法:

public static SmartEnumerable<T> AsSmart<T>(this IEnumerable<T> source)
{
    return new SmartEnumerable<T>(source);
}
(这个例子听起来有点滑稽)

编辑


根据Jon Skeet的说法,我将
ToSmart
重命名为
AsSmart

,这是一个快速更新-现在可以在MiscUtil中使用。根据上的示例:

//老路
foreach(智能可数.Entry in
新智能数字(列表))
//更好的方法
foreach(智能可数.Entry in
SmartEnumerable.Create(列表))
//最佳方式(C#3.0)
foreach(list.AsSmartEnumerable()中的var条目)

这个问题是为了“最能提到飞碟手的帖子”这个可疑的荣誉吗?巧妙地利用飞碟信号来吸引他的注意力。看看你身后。他会一声不响地出现的。哦,不!我的秘密隐藏双向飞碟信号文本可见;-)似乎连乔恩都无法追踪自己,所以当他睡着的时候这没关系——我依靠我的手下为我提供完美的答案;)为此,感谢Bryan和Jared…尝试播放更多,但仍然得到:错误44使用泛型类型“MiscUtil.Collections.SmartEnumerable”需要“1”类型参数-在myCats行上myCats的确切类型是什么?IEnumerable-实际上它的类型是“InfoPanelEntry[]”,但这很无聊。我尝试了IEnumerable myCats=null;为了得到准确的[编译时间]error@jaredpar-乔恩的课还是不好学。尝试从顶部的链接下载SmartEnumerable类。您的代码可以按原样编译,但不能与我包含的构造函数和类定义结合使用above@Simon:使用Jared的额外代码(我将很快在MiscUtil中包含类似的内容;在这里使用类型推断显然是有意义的)。这一个可以工作:)我喜欢这一个。让我想知道其他的方法。我只是想思考泛型方面的问题,所以我甚至没有尝试跳出框框去思考。我想你也可以做显式的cast转换(?),但这有点讨厌syntactically@bryan-我们的猫很聪明,所以我能理解-。我从大约8岁起就使用“猫”、“狗”、“老鼠”作为变量名,尽管到目前为止我还没有把它们当作宠物。我想仓鼠是有点长的类型时,你没有智能这是很好的。将包括类似的内容。我仍然想要一个比“智能数字”更好的名字,但我想不出任何东西…@jon我想不出任何有趣的名字,甚至一个好的无聊的名字,但我会继续思考。同样好奇的是,你找到骷髅柱的哪种方法让你找到了我的…;-)无论哪种方式,在使用varI时,能够执行ToSmart()对于MVC UI编码都是非常宝贵的。我想我会将其称为AsSmartEnumerable,而不是ToSmartEnumerable—它将其包装,而不是立即进行计算。也必须检查执行情况。太好了!谢谢你,乔恩。这有助于MVC UI的工作。非常优雅的解决方案。我总是想知道为什么没有办法得到索引,但总是抱怨而不是修正它。回到我的新Kindle上阅读你的书2:-)我的荣幸-很高兴它能帮上忙。我不知道我的书在Kindle上有售。酷:)希望你喜欢。
new SmartEnumerable(myCats);
public static class SmartEnumerable {
  public static SmartEnumerable<T> Create<T>(IEnumerable<T> source) {
    return new SmartEnumerable<T>(source);
  }
}

void Example() {
  IEnumerable<string> myCats = GetMyCats();
  var se = SmartEnumerable.Create(myCats);
}
public static SmartEnumerable<T> AsSmart<T>(this IEnumerable<T> source)
{
    return new SmartEnumerable<T>(source);
}
var smartEnumerable = myCats.AsSmart();
// Old way
foreach (SmartEnumerable<string>.Entry entry in
                 new SmartEnumerable<string>(list))

// Better way
foreach (SmartEnumerable<string>.Entry entry in
                SmartEnumerable.Create(list))

// Best way (C# 3.0)
foreach (var entry in list.AsSmartEnumerable())