【问题标题】:Why cant the compiler infer the type for me? (aka Smarter SmartEnumerable)为什么编译器不能为我推断类型? (又名 Smarter SmartEnumerable)
【发布时间】:2010-10-07 08:27:58
【问题描述】:

我正在使用 Jon Skeet 非常聪明的 SmartEnumerable。如果你还没有看过,我建议你去看看。

类已定义:

public class SmartEnumerable<T> : IEnumerable<SmartEnumerable<T>.Entry>

构造函数是:

public SmartEnumerable(IEnumerable<T> enumerable)

然后你通过说来使用它:

new SmartEnumerable<Cat>(myCats);  // where myCats is IEnumerable<Cat>

现在我真的很想让编译器推断我有一组猫,并且能够说:

new SmartEnumerable(myCats);

但是这给了我一个编译器错误:

方法的类型参数 'MiscUtil.Collections.SmartEnumerable.SmartEnumerable(System.Collections.Generic.IEnumerable)' 不能从用法中推断出来。尝试 指定类型参数 明确的。

我不清楚这是为什么。有没有办法解决它。为什么它看不到我正在使用IEnumerable&lt;Cat&gt; 并从中推断。我可以更改任何内容以使其识别我正在使用的类型吗?

我真的很想用某种方法来构造 SmartEnumerable 而不必指定类型 - 因为我主要将它用于 ASP.NET MVC 中的 UI,而我并不总是将 includes 用于类型并依赖在var 上给我一个参考。我最终不得不包含类型才能使用 SmartEnumerable - 这降低了它的优雅性。

哦,我会直接给约翰发电子邮件,但无论如何他可能会在这里回复得更快:-)


&lt;font color=white&gt;skeet skeet skeet, jon, jon, jon, jon skeet, skeet jon, skeetster, skeetmeister&lt;/font&gt;

【问题讨论】:

  • 这个问题是为了获得“最常提及 The Skeetster 的帖子”这个可疑的荣誉吗?
  • 巧妙地使用飞碟信号来引起他的注意。看看你后面。他会不发声地出现。
  • 哦不!我的秘密隐藏的 skeet-signal 文本可见 ;-)
  • 看起来即使乔恩在睡觉时也无法在 SO 上追踪自己
  • 没关系 - 我依靠我的奴才为我提供完美的答案;)为此,谢谢 Bryan 和 Jared...

标签: c# generics


【解决方案1】:

试试这个代码

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);
}

您的代码失败了,因为 C# 无法推断构造函数的泛型参数。但是 C# 不仅能够推断出其他方法的泛型参数。

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

【讨论】:

  • 尝试再玩一些,但仍然得到:错误 44 使用泛型类型 'MiscUtil.Collections.SmartEnumerable' 需要 '1' 类型参数 - 在 myCats 行上
  • myCats 的确切类型是什么?
  • IEnumerable - 实际上它的类型是 'InfoPanelEntry[]' 但那很无聊。我试过 IEnumerable myCats = null;得到那个确切的[编译时间]错误
  • @jaredpar - jon 的课仍然没有用。尝试从顶部的链接下载 SmartEnumerable 类。您的代码可以按原样编译 - 但不能与我上面包含的构造函数和类定义结合使用
  • @Simon:这绝对可以用 Jared 的额外代码(我很快会在 MiscUtil 中包含类似的东西;在这里使用类型推断显然很有意义)。
【解决方案2】:

我同意 JaredPar。我想指出你也可以做一个扩展方法:

public static SmartEnumerable<T> AsSmart<T>(this IEnumerable<T> source)
{
    return new SmartEnumerable<T>(source);
}

你会这样使用它:

var smartEnumerable = myCats.AsSmart();

(这个例子听起来很有趣)

编辑

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

【讨论】:

  • 这个有效 :) 我喜欢这个。让我想知道其他方法。我只是想考虑泛型方面,所以甚至没有尝试开箱即用。我想你也可以做一个显式转换转换器(?),但这在语法上有点恶心
  • @bryan - 我们的猫很聪明,所以我可以联系起来 - ike.simonweaver.com。自从我大约 8 岁以来,我就一直使用“cat”、“dog”、“mouse”作为变量名,尽管直到现在还没有将它们作为宠物。我想当你没有智能感知时,仓鼠打字有点长
  • 这也不错。将包括类似的东西。我仍然想要一个比“SmartEnumerable”更好的名字,但我想不出任何东西......
  • @jon 我想不出任何有趣的名字,甚至是一个无聊的好名字,但我会继续思考。也很好奇你找到 skeetposts 的哪种方法让你找到了我的……;-) 使用 var
  • 我想我会称它为 AsSmartEnumerable 而不是 ToSmartEnumerable - 它包装它而不是立即评估。也必须检查实现。
【解决方案3】:

快速更新 - 现在在 MiscUtil 本身中可用。根据usage page 上的示例:

// 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())

【讨论】:

  • 太棒了!谢谢乔恩。这有助于 MVC UI 工作的 TONNE。非常优雅的解决方案。我一直想知道为什么没有办法获取索引,但总是抱怨而不是修复它。回到我的新 Kindle 2 上阅读你的书 :-)
  • 我很高兴 - 很高兴它有帮助。我不知道我的书可以在 Kindle 上找到。酷 :) 希望你喜欢它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-23
  • 1970-01-01
  • 2021-03-11
相关资源
最近更新 更多