最近,我一直在阅读一些有关始终使用属性而不是C#中的公共字段的主题,但是私有属性呢?当然,有一些关于它的线程,但是他们几乎总是谈论附加的逻辑/延迟加载等。
假设我有一个只读字段,它将在Program类的所有位置进行访问,但是(至少到目前为止)在其他任何地方都没有使用它:
static class Program
{
private static readonly Canvas canvas = new Canvas(100, 30);
// Canvas is like the main class of my game, there can be only one instance of it
static void Main()
{
// ...
canvas.DoSomething();
// ...
}
// ...
// Many other references to "canvas" here
}
或者我应该做这样的事情:
private static Canvas Canvas { get; } = new Canvas(100, 30);
第二个选项意味着我可以轻松地将此信息公开,以后可能会也可能不会。那其他私人领域呢?是否有关于私有财产的规则或指南?还是我应该将所有内容都声明为字段,因为它是私有的(尽管感觉像是公共场合的?)]
仅作说明:
使用私有属性是无用的,因为只有当前的类成员才能访问它,并且可以读写。
除非您只想在构造函数中或在声明级别初始化它,并且不允许在其他方法中写入,所以可以编写:
private MyField { get; }
声明只读字段和此类属性之间的区别在于,属性读取访问器是一种方法,因此它导致每次访问都消耗CPU proc调用滴答,而不需要只读属性。
所以这是速度性能的问题,否则是相同的确定性。
这里是测试班:
public class Test
{
private readonly int MyField = 10;
private int MyProperty { get; }
public Test()
{
MyProperty = 10;
}
public void Method()
{
var value1 = MyField;
var value2 = MyProperty;
}
}
这里是编译器生成的IL代码:
// int myField = MyField;
IL_0001: ldarg.0
IL_0002: ldfld int32 ConsoleApp.Test::MyField
IL_0007: stloc.0
// int myProperty = MyProperty;
IL_0008: ldarg.0
IL_0009: call instance int32 ConsoleApp.Test::get_MyProperty()
IL_000e: stloc.1
对于只读字段,只有一个值装入堆栈,CLR将该值替换为目标处理器,装入寄存器指令是快速(MOV)。
[具有一个属性,有一个.NET方法调用,CLR将其替换为目标处理器过程调用指令,该指令会占用很多CPU滴答声以及返回(CALL / RET)。
.method private hidebysig specialname instance int32 get_MyProperty () cil managed
// return MyProperty;
IL_0000: ldarg.0
IL_0001: ldfld int32 ConsoleApp.Test::'<MyProperty>k__BackingField'
IL_0006: ret
因此,一个属性比一个只读字段需要更多的CPU周期,但是在操作方面,结果是相同的(我会说一个错误的值,因为我不记得x486了,它很旧,但是可以想象是大约有5到20倍的速度变慢了)。
因此,如果速度不是很关键,则应优先考虑。您可以毫无问题地更改为公众,高级设计保持不变:速度和外观没有其他区别。
也就是说,请记住,例如,Visual Studio设计器,组件设计和序列化需要公共属性。因此,使用属性可能会节省时间并且更加明智。
https://superuser.com/questions/643442/latency-of-cpu-instructions-on-x86-and-x64-processors