请注意,这个问题只涉及性能。让我们跳过设计指南、哲学、兼容性、可移植性以及任何与纯性能无关的内容。谢谢。
现在来看问题。我一直认为,因为C#的getter/setter实际上是伪装成方法的,所以读取公共字段必须比调用getter更快。
因此,为了确保我做了一个测试(下面的代码)。然而,这个测试只有在你从Visual Studio内部运行它时才会产生预期的结果(即字段比getter快34%)如果你从命令行运行它,它将显示几乎相同的时间……
唯一的解释可能是CLR进行了额外的优化(如果我在这里错了,请纠正我)。
我不相信在真正的应用程序中,这些属性被用于更复杂的方式时,它们会以同样的方式进行优化。
请帮助我证明或否定这个想法,在实际应用程序中,属性是否比字段更慢。
问题是 - 我应该如何修改测试类,使CLR改变行为,使公共字段优于getter。或者展示给我,没有内部逻辑的任何属性在getter方面的表现都和字段相同(至少如此)。
编辑:我只谈论Release x64版本。
现在来看问题。我一直认为,因为C#的getter/setter实际上是伪装成方法的,所以读取公共字段必须比调用getter更快。
因此,为了确保我做了一个测试(下面的代码)。然而,这个测试只有在你从Visual Studio内部运行它时才会产生预期的结果(即字段比getter快34%)如果你从命令行运行它,它将显示几乎相同的时间……
唯一的解释可能是CLR进行了额外的优化(如果我在这里错了,请纠正我)。
我不相信在真正的应用程序中,这些属性被用于更复杂的方式时,它们会以同样的方式进行优化。
请帮助我证明或否定这个想法,在实际应用程序中,属性是否比字段更慢。
问题是 - 我应该如何修改测试类,使CLR改变行为,使公共字段优于getter。或者展示给我,没有内部逻辑的任何属性在getter方面的表现都和字段相同(至少如此)。
编辑:我只谈论Release x64版本。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace PropertyVsField
{
class Program
{
static int LEN = 20000000;
static void Main(string[] args)
{
List<A> a = new List<A>(LEN);
List<B> b = new List<B>(LEN);
Random r = new Random(DateTime.Now.Millisecond);
for (int i = 0; i < LEN; i++)
{
double p = r.NextDouble();
a.Add(new A() { P = p });
b.Add(new B() { P = p });
}
Stopwatch sw = new Stopwatch();
double d = 0.0;
sw.Restart();
for (int i = 0; i < LEN; i++)
{
d += a[i].P;
}
sw.Stop();
Console.WriteLine("auto getter. {0}. {1}.", sw.ElapsedTicks, d);
sw.Restart();
for (int i = 0; i < LEN; i++)
{
d += b[i].P;
}
sw.Stop();
Console.WriteLine(" field. {0}. {1}.", sw.ElapsedTicks, d);
Console.ReadLine();
}
}
class A
{
public double P { get; set; }
}
class B
{
public double P;
}
}