在阅读了不同c#项目的一些源代码之后,我注意到关于公共“ getter”和私有“ setter”属性的书写方式几乎相同(几乎)。
仅具有属性的第一种方式:
public int x { get; private set; }
具有表达主体属性的第二种方法:
private int _x;
public int x => _x;
我知道public int x { get; }
等同于
private readonly int __x;
public int x { get { return __x } }
因此,我了解在单个“ getter”的情况下表达式主体属性与正常属性之间的区别。 我不明白的是,当有一个私有字段保存引用的值时的区别。我认为第二个可能更快,因为您可以直接访问该字段,而不是在类内部进行方法调用。 仅仅是样式上的差异,还是示例之一更快,更健壮等?
答案 0 :(得分:1)
您有两组等效的构造。
组1
当您不需要对构造函数外部的后备字段进行写访问时,可以使用以下任何一种结构:
private readonly int _x;
public int x => _x;
或
private readonly int _x;
public int x { get => _x; }
或
private readonly int _x;
public int x { get { return _x; } }
或
public int x { get; }
第2组
当需要访问构造函数外部的后备字段时,可以使用以下任何一种构造:
private int _x;
public int x => _x;
或
private int _x;
public int x { get => _x; }
或
private int _x;
public int x { get { return _x; } }
或
public int x { get; private set; }
您可以期望所有替代方案都同样快。在最后一个构造中,编译器将注入一个setter方法(对于每个自动属性,它还将注入一个backer字段)。在其他情况下,您可以直接访问该字段。注入的setter几乎肯定会被抖动内联,这消除了方法调用的性能损失。检查this Q&A以获得有关JIT内联的详细信息。
无疑,automatic属性更加简洁,这使您的代码更加整洁,尤其是当您拥有许多属性时。但归根结底,这取决于个人喜好(或您团队的编码规则)。
答案 1 :(得分:0)
如果使用私有后备字段,那么您正在封装信息并创建更可靠的代码。在某些情况下还可以提高可读性。
还有一个事实是,值安全地存储在字段中,因此,如果您的getter和setter方法中包含逻辑,将来需要更改,则它将与实际值存储区分开,从而使将来的实现更改变得更容易>
答案 2 :(得分:0)
请注意,如果您在构造函数中初始化属性,甚至还有另一种可能性
public int X { get; }
这是C#6.0中引入的仅吸气剂属性。您可以在构造函数中分配它(然后再也不需要)
public MyClass (int x) // Constructor
{
X = x;
}
或使用初始化程序
public int X { get; } = 100;
您不应该担心这些事情的速度。创建易于阅读且健壮的代码。 C#编译器或Jitter(在应用程序启动时运行的及时编译器,并且首次调用方法)可能会内联代码,甚至不调用getter或setter。
正常和表达体属性,方法和构造函数之间的区别仅是语法性质。行为没有差异。两种变体产生相同的已编译IL代码,因此,速度没有差异。
public int X => _x;
只是public int X { get { return _x; } }
的较短语法。这也称为syntactic sugar。