Второй вопрос здесь, «когда следует использовать поле вместо свойства?», Только кратко затронут в этом другом ответе и вроде и этом тоже , но не очень много деталей.
В общем, все остальные ответы на тему хорошего дизайна: предпочитайте выставлять свойства, а не выставлять поля. Хотя вы, вероятно, не будете регулярно ловить себя на мысли: "Ого, представьте, насколько хуже было бы, если бы я сделал это поле вместо свойства", это намного реже подумать о ситуации, когда вы скажете: «Ух ты, слава Богу, я использовал здесь поле вместо свойства».
Но есть одно преимущество, которое поля имеют над свойствами, и это их способность использоваться в качестве параметров "ref" / "out". Предположим, у вас есть метод со следующей подписью:
public void TransformPoint(ref double x, ref double y);
и предположим, что вы хотите использовать этот метод для преобразования массива, созданного следующим образом:
System.Windows.Point[] points = new Point[1000000];
Initialize(points);
Вот, я думаю, самый быстрый способ сделать это, поскольку X и Y - это свойства:
for (int i = 0; i < points.Length; i++)
{
double x = points[i].X;
double y = points[i].Y;
TransformPoint(ref x, ref y);
points[i].X = x;
points[i].Y = y;
}
И это будет очень хорошо! Если у вас нет измерений, которые доказывают обратное, нет никаких причин вонять. Но я считаю, что технически не гарантировано, что он будет так быстр:
internal struct MyPoint
{
internal double X;
internal double Y;
}
// ...
MyPoint[] points = new MyPoint[1000000];
Initialize(points);
// ...
for (int i = 0; i < points.Length; i++)
{
TransformPoint(ref points[i].X, ref points[i].Y);
}
Выполняя некоторые измерения , версия с полями занимает около 61% времени как версия со свойствами (.NET 4.6, Windows 7, x64, режим выпуска, отладчик не подключен). Чем дороже становится метод TransformPoint
, тем меньше становится разница. Чтобы повторить это самостоятельно, бегите с закомментированной первой строкой и без закомментированной.
Даже если для вышеуказанного не было выигрыша в производительности, есть другие места, где может быть полезна возможность использования параметров ref и out, например, при вызове Interlocked или Volatile семейство методов. Примечание. В случае, если это новость для вас, Volatile - это, по сути, способ получить то же поведение, которое обеспечивает ключевое слово volatile
. Таким образом, как и volatile
, он волшебным образом не решает всех проблем безопасности потоков, так как его название предполагает, что он мог бы.
Я определенно не хочу показаться, что я выступаю за то, чтобы вы говорили: «О, я должен начать выставлять поля вместо свойств». Дело в том, что если вам нужно регулярно использовать эти члены в вызовах, которые принимают параметры «ref» или «out», особенно для чего-то, что может быть простым типом значения, которому вряд ли когда-либо понадобится какой-либо из элементов свойств с добавленной стоимостью, аргумент может быть сделан.