The best place to investigate this is the C# language specification.
For example, in the case of enumerables, here are some snippets from the spec:
10.14.2 Enumerable interfaces
The enumerable interfaces are the
non-generic interface
System.Collections.IEnumerable and all
instantiations of the generic
interface
System.Collections.Generic.IEnumerable.
For the sake of brevity, in this
chapter these interfaces are
referenced as IEnumerable and
IEnumerable, respectively.
...
10.14.5.1 The GetEnumerator method
An enumerable object provides an
implementation of the GetEnumerator
methods of the IEnumerable and
IEnumerable interfaces. The two
GetEnumerator methods share a common
implementation that acquires and
returns an available enumerator
object. The enumerator object is
initialized with the argument values
and instance value saved when the
enumerable object was initialized, but
otherwise the enumerator object
functions as described in §10.14.4.
This ties in nicely with how these interfaces are actually defined in the .NET BCL, although it would be completely possible for a different (i.e. non-.NET) framework to provide a similar, compatible implementation that a C# compiler could then target.
Portions of the spec that are hard to separate from the .NET framework are normally marked with:
Note: This section is applicable only to the Microsoft .NET implementation of C#.
On another note,foreach
doesn't actually requireIEnumerable
; it can use a sort of 'duck-typing', which you can read about in section 8.8.4 of the spec.