何时使用私有属性(没有特殊逻辑)

When to use private properties (with no special logic)

最近我一直在阅读一些关于在 C# 中总是使用属性而不是 public 字段的话题,但是私有属性呢?当然,有一些讨论,但他们几乎总是在谈论额外的逻辑/延迟加载等。

假设我有一个只读字段,将在整个程序中访问 class,但(至少目前)它没有在其他任何地方使用:

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);

第二个选项意味着我可以很容易地做到这一点 public,我将来可能会或可能不会这样做。那么其他私有领域呢?关于什么应该是私有 属性 是否有任何规则或指南?或者我应该将所有内容都声明为一个字段,因为它是私有的(尽管感觉 public-ish)?

澄清一下:

使用私有属性是没有用的,因为只有当前 class 成员可以访问它并且它是可读写的。

除非你只想在构造函数或声明级别初始化它,并且不允许在其他方法中写入,所以你可以这样写:

private MyField { get; }

声明只读字段和这样的 属性 之间的区别在于 属性 读取访问器是一种方法,因此它会导致 CPU proc 调用 tick 在每次访问时消耗,即不需要只读 属性.

所以这是速度性能的问题,否则它是相同的最终结果。

这是一个测试class:

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 滴答以及 return (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 倍。

因此,如果速度不是关键,这是一个偏好问题。您可以毫无问题地更改为 public,高级设计保持不变:速度和外观没有区别。

也就是说,请记住 public 属性对于 Visual Studio 设计器、组件设计和序列化是必需的。所以使用properties可能是一种时间的收获,也是一种更聪明的方式。

https://superuser.com/questions/643442/latency-of-cpu-instructions-on-x86-and-x64-processors

A 属性 是私有变量之上的包装。

私有 属性 与私有变量一样好。没有区别。 如果您不打算使用 class 之外的变量,那么只需使用变量

你也用过readonly。 readonly 的唯一目的是它只能在构造函数内部启动。

希望这能回答您的问题。