Обратите внимание, что этот вопрос касается только производительности. Давайте пропустим рекомендации по дизайну, философию, совместимость, переносимость и все, что не связано с чистой производительностью. Спасибо.
Теперь к вопросу. Я всегда предполагал, что, поскольку геттеры / сеттеры C # действительно являются замаскированными методами, чтение открытого поля должно быть быстрее, чем вызов геттера.
Итак, чтобы убедиться, что я сделал тест (код ниже). Однако этот тест дает только ожидаемые результаты (т. Е. поля быстрее, чем получатели на 34% ) , если вы запускаете его из Visual Studio.
Когда вы запускаете его из командной строки, он показывает примерно то же время ...
Единственное объяснение может быть в том, что CLR выполняет дополнительную оптимизацию (поправьте меня, если я ошибаюсь).
Я не верю, что в реальном приложении, где эти свойства используются гораздо более изощренным образом, они будут оптимизированы таким же образом.
Пожалуйста, помогите мне доказать или опровергнуть идею о том, что в реальной жизни свойства медленнее полей.
Вопрос в том, как мне изменить тестовые классы, чтобы поведение CLR изменилось так, чтобы открытое поле превзошло геттеры. ИЛИ покажите мне, что любое свойство без внутренней логики будет работать так же, как поле (по крайней мере, на получателе)
РЕДАКТИРОВАТЬ: я говорю только о выпуске сборки 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;
}
}