Buy Me a Coffee

Buy Me a Coffee!

Tuesday, January 31, 2017

The Version of Visual Studio you are running matters

Let's pretend for a second that you and a colleague are about to start a project together.  Let's also pretend that you are going to be using C# to develop the project.  You get together and poll your other colleagues and determine that .NET Framework 4.5.2 is the only way to go.  You are done now, right?  Anything else to discuss?  Ok, you will use GIT for source control.  Enough?  Tabs and not spaces, no regions.  Surely you are done now, right?  What about Visual Studio version?  Not Edition, Version.  You should, otherwise your friend might not be able to compile you write.
Wait, doesn't the .NET Framework version dictate the language features you have available?  Do you doubt me?  Open up Visual Studio 2013 and try adding the following code to some class:


        public static string ExampleProperty { get; set; } = "Yowza!";

What do you get?  I get:
    Invalid token '=' in class, struct, or interface member declaration

Syntax error on Property initialization in VS 2013
Ok, maybe I am just writing bad code?  Try the same thing in VS 2015.  Works doesn't it?  Are you getting the picture?  Do I have your attention yet?
Well, what happens when we decompile the assembly created by VS 2015?  We get this:


using System;
using System.Runtime.CompilerServices;
 
namespace BlogPost
{
    internal class Program
    {
        public static string ExampleProperty
        {
            get;
            set;
        }
 
        static Program()
        {
            Program.ExampleProperty = "Yowza!";
        }
 
        public Program()
        {
        }
 
        private static void Main(string[] args)
        {
            Console.WriteLine(Program.ExampleProperty);
        }
    }
}

Look familiar?  What would happen if we already had a static Program() method?  Let's try and find out!

If we start with this:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace BlogPost
{
    class Program
    {
        public static string ExampleProperty { get; set; } = "Yowza!";
 
        public static string ExampleVariable;
        static Program()
        {
            ExampleVariable = "wow";
        }
 
        static void Main(string[] args)
        {
            Console.WriteLine(ExampleProperty);
            Console.WriteLine(ExampleVariable);
        }
    }
}

We end up with this when we decompile:


using System;
using System.Runtime.CompilerServices;
 
namespace BlogPost
{
    internal class Program
    {
        public static string ExampleVariable;
 
        public static string ExampleProperty
        {
            get;
            set;
        }
 
        static Program()
        {
            Program.ExampleProperty = "Yowza!";
            Program.ExampleVariable = "wow";
        }
 
        public Program()
        {
        }
 
        private static void Main(string[] args)
        {
            Console.WriteLine(Program.ExampleProperty);
            Console.WriteLine(Program.ExampleVariable);
        }
    }
}

Interesting isn't it?  That is part of why I am looking into the internals of the binary files produced by different frameworks and different compilers.  Don't get upset when your Dev Lead or Architect won't let you move to the latest and greatest compiler.  There is a reason why standards are important in all things.

Keep having fun, and asking questions!