The SLAR on System.CharEnumerator
Continuing in the series on sharing some of the information in the .NET Framework Standard Library Annotated Reference Vol 1 here is an annotation from the System.CharEnumerator class.
BA - Our reason for adding this class to the BCL was not that we felt there was a
huge demand for enumerating characters. It was required to enable efficient support
for applying foreach over strings. Simply using IEnumerator would have caused
a boxing operation for each character accessed out of the string.
string s = “John Smith”;
foreach (char c in s) {
Console.WriteLine (“{0}-”, c);
}
A side note on this is that the C# compiler now does not even use this class. It special cases
foreach over strings and generates very efficient code for accessing a string
that not only avoids the boxing operation, but is also as good as you could do with a
for loop. In particular it does not pay the cost of another allocation for the enumerator,
and takes full advantage of JIT optimizations.
This is a classic example of why explicit method implementation is such an important
feature. Notice that we have both:
object IEnumerator.Current { get; }
public char Current { get; }
We needed to have Current property return Object to satisfy the IEnumerator
interface. But we also wanted to have a Current property that returned a char such
that usage of this type would not force a boxing operation for each access and to make
usage easier (no ugly casts). However in C# (and the CLS) it is not possible to differ
only by return type. So we explicitly implement the Object version such that the
property is only there when cast to the interface.
Brian Grunkemeyer - The key point to understand about private interface implementation (using the C#
terminology although it is more properly a subset of the CLI feature we call methodimpls)
is that it allows you to override an interface method based on its return type.
While it also allows you to provide different method implementations for two different
versions of a method coming from different interfaces, in practice most people try to avoid
problems like this. Multiple inheritance of interfaces, but not classes, seems to make the
classic diamond inheritance pattern rarer, or at least significantly less confusing.