Лучшее место для изучения этого - спецификация языка C # .Например, в случае перечислимых, вот некоторые фрагменты из спецификации:
10.14.2 Перечислимые интерфейсы
Перечислимые интерфейсы не являютсяуниверсальный интерфейс System.Collections.IEnumerable и все экземпляры универсального интерфейса System.Collections.Generic.IEnumerable.Для краткости в этой главе эти интерфейсы обозначены как IEnumerable и IEnumerable, соответственно.
...
10.14.5.1 Метод GetEnumerator
Перечислимый объект обеспечивает реализацию методов GetEnumerator интерфейсов IEnumerable и IEnumerable.Два метода GetEnumerator имеют общую реализацию, которая получает и возвращает доступный объект перечислителя.Объект перечислителя инициализируется значениями аргументов и значением экземпляра, сохраненными при инициализации перечислимого объекта, но в противном случае объект перечислителя функционирует, как описано в §10.14.4.
Это хорошо согласуется с тем, какинтерфейсы на самом деле определены в .NET BCL, хотя для другой (т.е. не .NET) инфраструктуры вполне возможно обеспечить аналогичную совместимую реализацию, на которую затем мог бы нацеливаться компилятор C #.*
Части спецификации, которые трудно отделить от .NET framework, обычно помечаются:
Примечание. Этот раздел применим только к реализации Microsoft CNET для C #.
С другой стороны, foreach
на самом деле не требует IEnumerable
;он может использовать своего рода «типизацию утки», о которой вы можете прочитать в разделе 8.8.4 спецификации.