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.