【问题标题】:How an auto property is compiled?自动属性是如何编译的?
【发布时间】:2016-07-11 19:02:46
【问题描述】:

在我看到一些关于属性和自动属性以及编译器如何表示它们的问题和答案后,我问这个问题。

据我了解,自动属性表示为一个字段,有两种方法,一个 getter 和一个 setter。在这种情况下,如果使用字段,访问该字段的代码应该比访问属性的代码更快,因为它避免了对方法的任何附加调用。为了证明这个理论,我编写了以下代码,请原谅它的外观:

public class A
{
    public int Prop { get; set; }
    public int Field;

    public A()
    {
        Prop = 1;
        Field = 1;
    }
}
class Program
{
    static void Main(string[] args)
    {
        List<long> propertyExecutionTimes = new List<long>();
        List<long> fieldExecutionTimes = new List<long>();

        A a = new A();
        int aux;
        for (int j = 0; j < 100; j++)
        {
            var watch = System.Diagnostics.Stopwatch.StartNew();
            for (int i = 0; i < 10000000; i++)
            {
                aux = a.Prop;
                a.Prop = aux;
            }
            watch.Stop();

            propertyExecutionTimes.Add(watch.ElapsedMilliseconds);

            watch = System.Diagnostics.Stopwatch.StartNew();
            for (int i = 0; i < 10000000; i++)
            {
                aux = a.Field;
                a.Field = aux;
            }
            watch.Stop();

            fieldExecutionTimes.Add(watch.ElapsedMilliseconds);
        }
        Console.WriteLine("Property best time: " + propertyExecutionTimes.OrderBy(x => x).First());
        Console.WriteLine("Field best time: " + fieldExecutionTimes.OrderBy(x => x).First());

        Console.ReadKey();
    }
}

它包括调用 10M 次一个字段,而不是调用 10M 次一个属性 10 次,然后从每个测试中选择最低值。 VS2012 发布版本的结果是:

Property best time: 96
Field best time: 45

因此,正如预期的那样,字段的结果比属性要好得多。

但是在此之后我在没有调试器的情况下运行了程序(只需运行 .exe 文件),令我惊讶的是,使用字段和这样的属性的时间相似:

Property best time: 20
Field best time: 20

在这种情况下,使用属性和字段之间的区别是没有的,这让我认为它们在这种情况下被编译为相同,或者属性的方法被转换为与inline 方法类似的东西C++。这让我觉得我应该看看实际的 getter 和 setter 是如何与属性相比的,所以我添加了一对 getter 和 setter:

private int _field;
public int Get() { return _field; }
public void Set(int value) { _field = value; }

对一个属性进行类似的测试,只是为了尊重相同的行为而进行了一些更改:

aux = a.Get();
a.Set(aux);

给我这个输出:

Property best time: 96
Methods best time: 96

使用调试器和:

Property best time: 20
Methods best time: 20

没有调试器。这些值是相同的,所以我得出结论,自动属性是 getter 和 setter,它们的编译就像字段一样。这是一个正确的结论吗?最后,为什么在附加调试器时字段也比属性快?

【问题讨论】:

  • 使用 C# 时实际上有两个编译步骤(假设您没有使用 .NET Native 之类的东西)。在“编译时”输出 MSIL 的 C# 编译器和在运行时生成机器代码的 JIT 编译器。 JIT 执行您推测的内联优化。当附加调试器以改善调试体验时,它还会生成不同的、次优的机器代码。
  • 谢谢@mikez,这并不能完全回答我的问题,但它是一个有价值的信息

标签: c# visual-studio-2012 properties compilation


【解决方案1】:

这些值是相同的,所以我得出结论,自动属性是 getter 和 setter,它们的编译方式就像字段一样。

是的,自动属性被实现为一个字段,以及该字段的 get 和可选的 set 访问器。

这是一个正确的结论吗?

出于错误的原因,但是是的。 :) 要准确查看自动属性是如何实现的,不要依赖时间,而是创建一个程序或库并在 MSIL 反汇编程序中打开它。如您所见,计时结果可能会产生误导。

最后,为什么在附加调试器时字段也比属性快?

在调试时,像内联这样的机会要少得多,因为内联使设置断点、支持编辑和继续等变得更加困难。主要是内联使属性访问器与直接字段一样快访问。

【讨论】:

  • 我不得不承认我到现在都没有反汇编任何二进制文件,所以花了我一些时间。首先我在Release模式下反汇编了一个dll构建,所以它并没有显示很多东西,但是当我在Debug中尝试版本时,我很惊讶!我能够看到整个结构是如何保持的。谢谢你的回答,它让我工作了一些,但这是值得的。祝你有美好的一天!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 2023-02-01
  • 1970-01-01
  • 2022-09-23
相关资源
最近更新 更多