C# 这是有效的C代码吗?

C# 这是有效的C代码吗?,c#,.net,compiler-construction,decompiler,C#,.net,Compiler Construction,Decompiler,这是有效的C代码吗 public class Product { [CompilerGenerated] private string <Name>k__BackingField; [CompilerGenerated] private decimal <Price>k__BackingField; public string Name { get; private set;

这是有效的C代码吗

  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);
    }
   }
上面的示例取自.NET反编译器的JustDecompile,您可以在下面看到原始版本:

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);
       }
   }
}

我想知道第一个清单是反编译错误还是由编译器生成的有效C代码。我对GetSampleProducts方法中的代码非常好奇。

将其粘贴到编译器中并尝试编译,很容易看出它不是有效的C代码

似乎反编译器不知道如何正确处理自动属性,对象文字语法也不确定这是否是正确的术语

k__BackingField的一点是,它实际上是在IL中生成的BackingField的名称。在C中不是标识符名称的有效部分,但是它们在IL中,这就是为什么在编译自动属性时它们会收到该名称,因此它不会与您自己创建的任何变量名称冲突。自动属性只是编译器的魔法,毕竟它确实在后台创建了一个私有字段

使用更完整的反编译器,您将获得更好的结果,例如,DotPeek在反编译时给出的结果,即使在删除调试符号的情况下进行了优化:

  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);
    }
  }

通过将其粘贴到编译器中并尝试编译,很容易看出它不是有效的C代码

似乎反编译器不知道如何正确处理自动属性,对象文字语法也不确定这是否是正确的术语

k__BackingField的一点是,它实际上是在IL中生成的BackingField的名称。在C中不是标识符名称的有效部分,但是它们在IL中,这就是为什么在编译自动属性时它们会收到该名称,因此它不会与您自己创建的任何变量名称冲突。自动属性只是编译器的魔法,毕竟它确实在后台创建了一个私有字段

使用更完整的反编译器,您将获得更好的结果,例如,DotPeek在反编译时给出的结果,即使在删除调试符号的情况下进行了优化:

  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);
    }
  }

最好的方法是你自己去编译代码,看看它是否是一个有效的C代码。如果最后它确实是一个有效的C代码,那么您应该阅读代码并思考它是否真的产生了相同的结果


请记住,一旦将代码编译成,代码本身就会丢失,因此反编译器会尝试编写一段代码,该代码会给出与IL相同的结果。。。但是编译器不可能总是给您一个原始代码的精确副本。

最好的方法是您获取该代码并尝试自己编译,以查看它是否是有效的C代码。如果最后它确实是一个有效的C代码,那么您应该阅读代码并思考它是否真的产生了相同的结果


请记住,一旦将代码编译成,代码本身就会丢失,因此反编译器会尝试编写一段代码,该代码会给出与IL相同的结果。。。但是编译器不可能总是给您原始代码的精确副本。

看起来反编译器被列表的初始化搞糊涂了。它肯定没有生成有效的C代码。它看起来像是在尝试创建列表中的项目,然后添加它们,但它没有完全正确。它总是很难反编译的东西,所以我希望必须作出调整,不时


您可以尝试编辑底部部分,显式添加4个新项目,并为它们命名。这可能会有所帮助。由于反编译器正在处理二进制文件,并且最终由编译器控制它,因此有时对算法的表达方式进行一些细微的调整会对其产生影响。

看起来反编译器被该列表的初始化搞糊涂了。它肯定没有生成有效的C代码。它看起来像是在尝试创建列表中的项目,然后添加它们,但它没有完全正确。它总是很难反编译的东西,所以我希望必须作出调整,不时


您可以尝试编辑底部部分,显式添加4个新项目,并为它们命名。这可能会有所帮助。由于反编译器使用的是二进制文件,最终由编译器控制,因此有时对算法的表达方式进行一些细微的调整会对其产生影响。

backingField字段和属性是半正确的:{get;private set;}语法被编译为backing字段,而属性则执行简单的赋值和访问。IL会将支持字段列为具有无效名称,这很好。但是,属性应该包含getter&setter的内容,是的,这是一个语法错误,因为字段名无效,但它是IL的准确表示。属性应该包含它们的编译体,或者处于{get;private set;}模式,并且不存在支持字段。同时具有支持字段和{ 收到私有集;}语法不正确

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 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;
}
应该是这样的:

List<Product> products = new List<Product>();
Product product1 = new Product();
product1.Name = "ProductA";
product1.Price = new decimal(1233, 0, 0, false, 2);
products.Add(product1);

backingField字段和属性有一半是正确的:{get;private set;}语法被编译为一个backingField,属性执行简单的赋值和访问。IL会将支持字段列为具有无效名称,这很好。但是,属性应该包含getter&setter的内容,是的,这是一个语法错误,因为字段名无效,但它是IL的准确表示。属性应该包含它们的编译体,或者处于{get;private set;}模式,并且不存在支持字段。同时使用支持字段和{get;private set;}语法是不正确的

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 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;
}
应该是这样的:

List<Product> products = new List<Product>();
Product product1 = new Product();
product1.Name = "ProductA";
product1.Price = new decimal(1233, 0, 0, false, 2);
products.Add(product1);

产品名称到哪里去了?一个明显非法的部分由自动生成的标识符组成,其中包含标识符中不允许使用的字符C,但CLR允许。您可以通过尝试编译它来确定它是否有效…就像上面所说的,只需通过编译器验证它。至于它是否会做同样的事情,从我看来,我认为它不会。正如David Heffernan所说,产品名称丢失了,您也完全丢失了第二个2个样本产品。产品名称到哪里去了?一个明显非法的部分是自动生成的标识符,其中包含标识符中不允许的字符C,但是CLR是允许的。你可以通过尝试编译它来发现它是否有效…就像上面所说的,只需通过编译器来验证它。至于它是否会做同样的事情,从我看来,我认为它不会。正如David Heffernan所说,产品名称丢失了,您也完全丢失了第二个2个示例产品。顺便说一句,它可能是我见过的最好的C反编译器,我相信它们可以正确处理这两种情况。没有附属关系,只是他们产品的粉丝,可能是我见过的最好的C反编译器,我相信他们可以正确处理这两种情况。没有关系,只是他们产品的粉丝