27

Let's say I want to demo to someone about the differences between foreach in C# 4.0 and 5.0.

So I write up my code snippet:

public static void Main()
{
    string[] fruits = { "Apple", "Banana", "Cantelope" };
    var actions = new List<Action>();
    foreach (var fruit in fruits)
    {
        actions.Add(() => Console.WriteLine(fruit));
    }

    foreach(var a in actions)
    {
        a();
    }   
}

But no matter how I compile it, it always works as it does in 5.0*. I've tried setting the language version in the csproj file (Build -> Advanced -> Language Version) and I've tried just building it on the command line:

csc myProgram.cs /langversion:4

I can't get it to work the "old" way. Any help? Bonus points if you can tell me how to do it on both the command line and Visual Studio.

* For anyone who doesn't know, in C#. <= 4.0 this would print Cantelope Cantelope Cantelope, while in C# 5.0+ it would (more intuitively) print Apple Banana Cantelope. Here's a link, and here's another.

Pharylon
  • 9,796
  • 3
  • 35
  • 59
  • how do you know its not compiling the old way – pm100 Apr 06 '15 at 17:21
  • 1
    It might help readers to point out what should be different in the two versions. Not a lot of people are aware of the change in how the loop variable is treated in closures. – Jeff Mercado Apr 06 '15 at 17:22
  • C# 4 had actions, and Lambda expressions. What do you think it should be doing that it's not? – Bob G Apr 06 '15 at 17:23
  • i think you expect old version to do Cantelope, Cantelope, Cantelope, it doesnt – pm100 Apr 06 '15 at 17:24
  • 2
    For the more canonical source: [Closing over the loop variable considered harmful](http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx) – Jeff Mercado Apr 06 '15 at 17:25
  • I added a note on what the difference is. C# changes between version 4 and 5. – Pharylon Apr 06 '15 at 17:26
  • under vs2012 - c# lang 4 it says Apple,banana, cantelope. – pm100 Apr 06 '15 at 17:33
  • 1
    @pm100 VS2012 came with C# 5.0, so you're just seeing the exact thing I'm posting about. :) Try the same thing in VS2010. – Pharylon Apr 06 '15 at 17:40
  • ok, but the interesting things is that yr second example link still fails under vs2012 but the first one does not – pm100 Apr 06 '15 at 20:19

1 Answers1

30

The purpose of the /langversion is only to make the compiler accept specific language constructs. It does not affect the actual behaviour of the compiler.

The documentation states that:

Causes the compiler to accept only syntax that is included in the chosen C# language specification.

and

Because each version of the C# compiler contains extensions to the language specification, /langversion does not give you the equivalent functionality of an earlier version of the compiler.

So to demonstrate the different behaviour, you will have to use a different csc.exe, installed with the right framework versions.

C:\Windows\Microsoft.NET\Framework\v3.5>csc /out:c:\temp\foo-35.exe c:\temp\foo.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.7903
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.


C:\Windows\Microsoft.NET\Framework\v3.5>c:\temp\foo-35.exe
Cantelope
Cantelope
Cantelope
Anders Abel
  • 67,989
  • 17
  • 150
  • 217