Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why C# compiler treated string class separately with foreach statement

Tags:

I clearly understand "Pattern-based" approach that uses C# compiler when it dealing with the foreach statement.

And from C# Language Specification (section 8.8.4) it is clear that first of all C# compiler tries to find GetEnumerator method and only then tries to find IEnumerable<T> and IEnumerable interfaces.

But its unclear for me, why C# compiler treats string separately (because the String class contains a method GetEnumerator that returns CharEnumerator and it also implements IEnumerable<char> and IEnumerable interfces):

string s = "1234";
foreach(char c in s)
  Console.WriteLine(c);

converts to

string s = "1234";
for(int i = 0; i < s.Length; i++)
  Console.WriteLine(s[i]);

But I can't find any exceptions in Language Specification regarding the String class. Could someone give some insights about this solution?

I tried with the C# 4 compiler. Here is the IL code for the previous code snippet:

IL_0000:  ldstr       "1234"
IL_0005:  stloc.0     
IL_0006:  ldloc.0     
IL_0007:  stloc.2     
IL_0008:  ldc.i4.0    
IL_0009:  stloc.3     
IL_000A:  br.s        IL_001E
IL_000C:  ldloc.2     
IL_000D:  ldloc.3     
IL_000E:  callvirt    System.String.get_Chars
IL_0013:  stloc.1     
IL_0014:  ldloc.1     
IL_0015:  call        System.Console.WriteLine
IL_001A:  ldloc.3     
IL_001B:  ldc.i4.1    
IL_001C:  add         
IL_001D:  stloc.3     
IL_001E:  ldloc.3     
IL_001F:  ldloc.2     
IL_0020:  callvirt    System.String.get_Length
IL_0025:  blt.s       IL_000C
like image 496
Sergey Teplyakov Avatar asked Jul 04 '11 14:07

Sergey Teplyakov


People also ask

Why is C used?

The C programming language is the recommended language for creating embedded system drivers and applications. The availability of machine-level hardware APIs, as well as the presence of C compilers, dynamic memory allocation, and deterministic resource consumption, make this language the most popular.

Why is C used in C?

%d is used to print decimal(integer) number ,while %c is used to print character . If you try to print a character with %d format the computer will print the ASCII code of the character.

Why should you learn C?

Being a middle-level language, C reduces the gap between the low-level and high-level languages. It can be used for writing operating systems as well as doing application level programming. Helps to understand the fundamentals of Computer Theories.

Why C is still used today?

C exists everywhere in the modern world. A lot of applications, including Microsoft Windows, run on C. Even Python, one of the most popular languages, was built on C. Modern applications add new features implemented using high-level languages, but a lot of their existing functionalities use C.


1 Answers

Good catch. I was aware that the compiler performed a similar optimization for arrays, but I didn't know that it did this for strings too.

The best I can get you is a call-out from the language specification that gives a compiler the right to stray from the 'canon' as long as it produces equivalent behaviour:

8.8.4 The foreach statement

[...] A foreach statement of the form foreach (V v in x) embedded-statement is then expanded to:

{
    E e = ((C)(x)).GetEnumerator();
    try {
        V v;
        while (e.MoveNext()) {
            v = (V)(T)e.Current;
            embedded-statement
        }
    }
    finally {
        … // Dispose e
    }
}

[...] An implementation is permitted to implement a given foreach-statement differently, e.g. for performance reasons, as long as the behavior is consistent with the above expansion.

like image 67
Ani Avatar answered Oct 03 '22 23:10

Ani