为什么我在此示例代码中没有出现语法错误?

Why I don't get syntax error in this sample code?

只是尝试使用 C# Lookup 集合的一些基础知识,发现这个简单的示例编译得很好,甚至 IGrouping 接口也应该设置 TElement作为整数。

string txt = "Hello world!";
ILookup<char, int> occurrences = Enumerable.Range(0, txt.Length).ToLookup(i => txt[i], i => i);

foreach (IGrouping<char, string> values in occurrences)
    Console.WriteLine($"{values.Key}: {string.Join(", ", values)}");

显然,我在无效转换时遇到 运行 时间错误。但我预计,这适用于编译器...

编译器使用的规则似乎是:

If the compiler can see that the value type or sealed class does not implement or inherit the type the programmer is trying to cast to/from, the cast is illegal at compile-time.

(感谢 Jeppe Stig Nielsen 在评论中提到这一点。)

如果您在示例中使用以下任一选项而不是 XXXX,则编译 foreach (XXXX values in occurrences) 的结果如下。注意 occurrences 是从 IGrouping<char, int>.

派生的 ILookup<char, int> 类型
  • public class MyClass { } 编译
  • public sealed class MyClass { } 编译时错误
  • public sealed class MyClass : IGrouping<char, int> {...} 编译
  • public sealed class MyClass : IGrouping<char, string> {...} 编译时错误
  • public struct MyStruct {} 编译时错误
  • public struct MyStruct : IGrouping<char, string> {...} 编译时错误
  • public struct MyStruct : IGrouping<char, int> {...} 编译

这是 Krzysztof Cwalina 的一篇很好的博客 post,它描述了如何在 foreach 中使用 Duck 输入:

C# 的 foreach 运算符已经使用鸭子类型。这可能会让某些人感到惊讶,但要在 C# 中支持 foreach,您不需要实现 IEnumerable!您所要做的就是:

提供一个 public 方法 GetEnumerator 不带参数并且 return 是一个有两个成员的类型:a) 一个不带参数的方法 MoveMext 和 return 一个布尔值,和 b) 一个 属性 Current 和一个 getter,return 是一个对象。