Search code examples
c#.netdecompiler

Is this valid C# code?


Is this valid C# code ?

  public class Product
  {
        [CompilerGenerated]
        private string <Name>k__BackingField;

    [CompilerGenerated]
    private decimal <Price>k__BackingField;

    public string Name
    {
     get;
     private set;
    }

    public decimal Price
    {
     get;
     private set;
    }

    public Product() 
        {
        }

    public static List<Product> GetSampleProducts()
    {
     List<Product> products = new List<Product>();
     Product num1.Price = new decimal(1233, 0, 0, false, 2).Add(num1);
     Product product1.Price = new decimal(1332, 0, 0, false, 2).Add(product1);
     Product num2.Price = new decimal(2343, 0, 0, false, 2).Add(num2);
     Product product2.Price = new decimal(2355, 0, 0, false, 2).Add(product2);
     return products;
    }

    public override string ToString()
    {
     return string.Format("{0}: {1}", this.Name, this.Price);
    }
   }

The example above is taken from JustDecompile ( a .NET decompiler ) you can see the original version below:

using System;
using System.Collections.Generic;
using System.Text;

namespace ProductV3
{
   public class Product
   {
       public string Name { get; private set; }
       public decimal Price { get; private set; }

       public Product() { }

       public static List<Product> GetSampleProducts()
       {
          return new List<Product>()
          {
              new Product() { Name = "ProductA", Price = 12.33M },
              new Product() { Name = "ProductB", Price = 13.32M },
              new Product() { Name = "ProductC", Price = 23.43M },
              new Product() { Name = "ProductD", Price = 23.55M }
          };
       }

       public override string ToString()
       {
          return string.Format("{0}: {1}", Name, Price);
       }
   }
}

I want to know if the first listing is a decompiling error or if it is valid C# code, generated by the compiler. I am very curios what is with the code in the method GetSampleProducts.


Solution

  • It's pretty simple to see that it's not valid C# code by pasting it into a compiler and trying to compile it.

    It seems like the decompiler doesn't know how to properly handle auto-properties and the object literal syntax (not sure if that's the proper term)

    One thing with <Price>k__BackingField that is actually the name of the backing field generated in IL. < and > aren't valid parts of an identifier name in C# however they are in IL which is why they receive that name when auto-properties are compiled, so it doesn't conflict with any variable names you might create yourself. Auto-properties are just compiler magic that actually does create a private field in the background after all.

    With a more complete decompiler you'll get better results, for example, this is what DotPeek gives when decompiling (even optimized with debugging symbols removed):

      public class Product
      {
        public string Name { get; private set; }
    
        public Decimal Price { get; private set; }
    
        public static List<Product> GetSampleProducts()
        {
          return new List<Product>()
          {
            new Product()
            {
              Name = "ProductA",
              Price = new Decimal(1233, 0, 0, false, (byte) 2)
            },
            new Product()
            {
              Name = "ProductB",
              Price = new Decimal(1332, 0, 0, false, (byte) 2)
            },
            new Product()
            {
              Name = "ProductC",
              Price = new Decimal(2343, 0, 0, false, (byte) 2)
            },
            new Product()
            {
              Name = "ProductD",
              Price = new Decimal(2355, 0, 0, false, (byte) 2)
            }
          };
        }
    
        public override string ToString()
        {
          return string.Format("{0}: {1}", (object) this.Name, (object) this.Price);
        }
      }