Кажется, здесь есть правило, которое использует компилятор:
Если компилятор может видеть, что тип значения или запечатанный класс не реализовать или наследовать тип, который программист пытается передать в/из, литье является незаконным во время компиляции.
(Благодаря Jeppe Стиг Nielsen за упоминание этого в комментариях.)
Вот результат компиляции foreach (XXXX values in occurrences)
, если вы используете одну из следующих вариантов вместо XXXX
в вашем примере. Обратите внимание: occurrences
имеет тип ILookup<char, int>
, который получен из IGrouping<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> {...}
Компилирует
Вот хороший блог post по Кшиштоф Квалина, который описывает, как утка, набрав в используемом в Еогеаспе:
Еогеаспа оператора C#»s уже использует утку печатать. Это может быть удивительно для некоторых, но для поддержки foreach в C# вам не нужно реализовывать IEnumerable
! Все, что вам нужно сделать, это:
Обеспечить публичный метод GetEnumerator
, который не принимает никаких параметров и возвращает тип, который имеет два элемента: а) метод MoveMext
, который не принимает никаких параметров и возвращает логическое значение, и б) недвижимости Current
с получатель, который возвращает объект.
@PeterDuniho: Мы можем согласиться на [этот вопрос и эти ответы] (http://stackoverflow.com/a/20205068/717732)? Это буквальный. Да, хотя ** название ** нечетно, вопрос и семантика/смысл/.. совпадают. – quetzalcoatl
@Quetzalcoatl: намного лучше, да ... это похоже на этот вопрос. Я думаю, что Скотт немного подошел к сорнякам ближе к концу своего ответа с делом о ковариации, но в остальном это разумное факсимиле этого Q & A. –