简体   繁体   English

表达式绑定属性和简单Getter属性之间的区别

[英]Difference between Expression-Bodied Properties and simple Getter Properties

After reading some source code of different c# project i noticed different ways of writing (almost) the same statement regarding public "getter" and private "setter" properties. 在阅读了不同c#项目的某些源代码之后,我注意到(几乎)关于公共“ getter”和私有“ setter”属性的不同书写方式(几乎)。

First way with only properties: 仅具有属性的第一种方式:

public int x { get; private set; }

Second way with expression-bodied properties: 具有表达主体属性的第二种方式:

private int _x;
public int x => _x;

I know that public int x { get; } 我知道public int x { get; } public int x { get; } is equivalent to public int x { get; }等同于

private readonly int __x;
public int x { get { return __x } }

So I understand the difference between expression-bodied and normal properties in the case of a single "getter". 因此,我了解在单个“ getter”的情况下表达式主体属性与正常属性之间的区别。 What i do not understand is the difference when there is a private field that holds the referenced value. 我不明白的是,当有一个私有字段保存引用的值时的区别。 I thought that maybe the second one is faster because you have access to the field directly instead of a method call inside your class. 我认为第二个可能更快,因为您可以直接访问该字段,而不是在类内部进行方法调用。 Is it just a stylistic difference or is one of the examples faster, more robust, etc? 这仅仅是风格上的差异,还是示例之一更快,更强大等?

You have two groups of constructs which are equivalent. 您有两组等效的构造。

Group 1 第一组

When you don't need write access to the backing field outside the constructor, you can use any of these constructs: 当您不需要对构造函数外部的后备字段进行写访问时,可以使用以下任何一种结构:

private readonly int _x;
public int x => _x;

or 要么

private readonly int _x;
public int x { get => _x; }

or 要么

private readonly int _x;
public int x { get { return _x; } }

or 要么

public int x { get; }

Group 2 2组

When you need access to the backing field outside the constructor, you can use any of these constructs: 当需要访问构造函数外部的后备字段时,可以使用以下任何一种结构:

private int _x;
public int x => _x;

or 要么

private int _x;
public int x { get => _x; }

or 要么

private int _x;
public int x { get { return _x; } }

or 要么

public int x { get; private set; }

You can expect all of the alternatives to be equally fast. 您可以期望所有替代方案的速度都一样快。 In the last construct the compiler will inject a setter method (it will inject a backer field too, as for every automatic property). 在最后一个构造中,编译器将注入一个setter方法(对于每个自动属性,它还将注入一个backer字段)。 In the other cases you access the field directly. 在其他情况下,您可以直接访问该字段。 The injected setter will almost certainly be inlined by the jitter, which removes the performance penalty of a method call. 注入的setter几乎肯定会被抖动内联,这消除了方法调用的性能损失。 Check this Q&A for details on JIT inlining. 检查此问答以获取有关JIT内联的详细信息。

The automatic property is certainly more concise, which makes your code neater, especially when you have many properties. 自动属性肯定更简洁,这使您的代码更加整洁,尤其是当您拥有许多属性时。 But at the end of the day it comes down to personal preference (or your team's coding rules). 但归根结底,这取决于个人喜好(或您团队的编码规则)。

If you use a private backing field, You are encapsulating the information and creating more robust code. 如果使用私有后备字段,则将封装信息并创建更可靠的代码。 It also improves the readability in some cases. 在某些情况下,它还提高了可读性。
There is also the fact that the value is stored safely in a field and so if you have logic within your getters and setters that needs to change in the future it is separated from the actual value store and makes changing that implementation easier in future 还有一个事实是,值安全地存储在字段中,因此,如果您的getter和setter方法中包含逻辑,将来需要更改,则它将与实际值存储区分开,从而使将来的实现更改更容易

Note that there's even another possibility if you initialize the property in the constructor 请注意,如果您在构造函数中初始化属性,则还有另一种可能性

public int X { get; }

This is a getter-only property introduced in C# 6.0. 这是C#6.0中引入的仅吸气剂属性。 You can assign it in the constructor (and then never again) 您可以在构造函数中分配它(然后不再分配)

public MyClass (int x) // Constructor
{
    X = x;
}

or with an initializer 或使用初始化程序

public int X { get; } = 100;

You should not care about speed for those things. 您不应该关心这些事情的速度。 Create an easy to read and robust code. 创建易于阅读且健壮的代码。 The C# compiler or the Jitter (Just In Time compiler running when the application starts, and methods are called for the first time) will possibly inline the code and not even call the getter or the setter. C#编译器或Jitter(在应用程序启动时运行的及时编译器,并且首次调用方法)可能会内联代码,甚至不会调用getter或setter。

The difference between normal and expression-bodied properties, methods and constructors is only of syntactical nature. 正常属性和表示形式的属性,方法和构造函数之间的区别仅是语法性质。 There is no difference in behavior. 行为没有差异。 Both variants produce the same compiled IL code and therefore, there is no difference in speed. 两种变体产生相同的已编译IL代码,因此,速度没有差异。

public int X => _x; is simply a shorter syntax for public int X { get { return _x; } } 只是public int X { get { return _x; } } public int X { get { return _x; } } . public int X { get { return _x; } } This is also called syntactic sugar . 这也称为语法糖

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM