4

I have a nice question about the loop-expression of a for-loop in C#.

I always like to learn and extend my knowledge so I often use my reflector to look and learn from other. Lately I was looking around in an assembly which I assume is a C# assembly.

I came across this:

public virtual void DoRows(Parse rows)
{
  for (; rows != null; {
    Parse more;
    rows = more;
  }
  )
  {
    more = rows.More;
    this.DoRow(rows);
  }
}

I never knew I could use a code-block in my loop-expression. So I fired up MSDN and went looking in the language reference of C# but found nothing.

The C++ reference shows some interesting things tho (http://msdn.microsoft.com/en-us/library/b80153d8.aspx), but I am not a C++ developper and I have a strong feeling the assmbly was not written in C++.

dotPeek says the assembly is a v4.0.30319 / msil assembly.

Now here are the questions: - Is this a C++ or a C# code-construct?! - Can we do things like this in C#?

I am not able to reproduce code that looks like that and compiles in VS2010.

@edit: changed the word assembly in code-construct.

@edit II: Thanks for all your answers. I think this is either a bug in the dotPeek reflector or we found some for-loop-expression easter eggs. This is what Red Gate says about the same method:

public virtual void DoRows(Parse rows)
{
    while (rows != null)
    {
        Parse more = rows.More;
        this.DoRow(rows);
        rows = more;
    }
}
Makoto
  • 104,088
  • 27
  • 192
  • 230

2 Answers2

2

There is no such thing as a C++ or C# assembly. Once the code is compiled, it is ILCode. The reflector takes this ILCode and decompiles it to the language you selected.

This can result in code that is valid in ILCode, but not valid in the target language.

Femaref
  • 60,705
  • 7
  • 138
  • 176
  • But that isn't C# code, and it isn't C++/CLI code. Your last sentence is incorrect (although that is what's supposed to happen, clearly there is a bug here). – Ben Voigt Jun 27 '12 at 13:30
  • It is correct. There are things that are perfectly valid in ILCode, but not in C# (for example). The reflector simply parses the ILCode and transforms it into the target language, but it doesn't compile it - that's why it can result in non compileable code. – Femaref Jun 27 '12 at 13:31
  • Then it isn't "transformed into the target language", now is it? IL doesn't have `while` loops or `for` loops, it only has conditional branches. In this case, the decompiler chose to generate an illegal for loop, when there's a perfectly valid way to express it as a while loop. – Ben Voigt Jun 27 '12 at 13:33
  • Baloney. IL does not have "tokens", it is a binary machine language for a hypothetical machine. – Ben Voigt Jun 27 '12 at 13:38
  • @Femaref, then how do I reproduce a for-loop like that in C# that makes it into IL that looks like that? Can you give an example? I mean, if the compiler can take some kind of for loop syntax and make it look like that, how can we as developers? Or could this be a dotPeek issue? – roy_carthago Jun 27 '12 at 13:40
  • @roy_carthago You could simply write IL code directly, without going through any compiler. If the structure and control flow (yes you'd be restricted to labels and jumps, but those are all you need to emulate higher-level control flow structures) matches whatever (a, or several) compiler(s) spit out for a `foreach`, a decompiler may be tricked. Because it is tuned to common and compiler-emitted code. –  Jun 27 '12 at 13:47
  • @Femaref True, thats what I understand. The strange thing is however, I picked this assembly up from FitNesse. A tool for executing Unit tests. Now I don't think they write IL directly for their software. How did this code end up in of their assemblies I still wonder... – roy_carthago Jun 27 '12 at 14:00
0

Compilation to IL is a many-to-one operation and decompilers have rules regarding which of the many choices they choose when decompiling. Often, different languages produce IL that is not possible to reproduce directly in another language.

In this instance either the decompiler has chosen poorly and the produced C# is invalid (a bug in the decompiler), or it cannot decompile the code into equivalent C#.

Rich O'Kelly
  • 41,274
  • 9
  • 83
  • 114
  • The controlling expressions in a `for` statement are *expressions*, not *statements*. A *block statement* is not an expression, and cannot be used as the increment *expression* of a for loop. – Ben Voigt Jun 27 '12 at 13:28
  • @BenVoigt the for statement refers to the `for (; ; )` statement. The expressions refer to the parts between the semi colons. Please read the MSDN page that I linked to. – Rich O'Kelly Jun 27 '12 at 13:30
  • 1
    I think you missed the whole point of the question. It's not the first (empty) expression that's invalid, it's the third one (between the semicolon and the closing parenthesis). – Ben Voigt Jun 27 '12 at 13:34
  • @Ben Voigt, you are correct. It is about the loop-expression not about the initialization-expression nor the condition-expression. – roy_carthago Jun 27 '12 at 13:36