简体   繁体   English

正确使用C#属性

[英]Correct use of C# properties

private List<Date> _dates;

public List<Date> Dates
{
    get { return _dates; }
    set { _dates = value; }
}

OR 要么

public List<Date> Dates
{
    get;        
    set;    
}

I have always used the former, is that incorrect or bad practice? 我一直使用前者,这是不正确还是不好的做法? It never occurred to me that I could just use the second option. 我从没想到我可以使用第二种选择。 I do like having my encapsulated variables to begin with an underscore so I can distinguish them from method parameters. 我喜欢让我的封装变量以下划线开头,因此可以将它们与方法参数区分开。 And I've just always done it that way. 我一直都是那样做的。

Is it possible that using the first option would result in an extra List<Date> object being instantiated and then the whole of _dates being replaced with value , or is it more intelligent than that? 使用第一个选项是否有可能导致实例化一个额外的List<Date>对象,然后将整个_dates替换为value ,或者比这更聪明?

Also, which is the most prominent in industry or is it totally subjective? 另外,哪个行业最突出或完全主观?

Use the former if you need to add some kind of logic to your getter/setters. 如果您需要在getter / setter方法中添加某种逻辑,请使用前者。

Use the latter otherwise. 否则使用后者。 It makes things much cleaner. 它使事情变得更加清洁。 You can also achieve read-only properties using auto properties: 您还可以使用自动属性来实现只读属性:

public List<Date> Dates { get; private set; }

Or, if you don't want people to add any items to the list through the property you can resort to the former syntax: 或者,如果您不希望人们通过该属性将任何项目添加到列表中,则可以采用前一种语法:

private List<Date> _dates = new List<Date>();
private ReadOnlyCollection<Date> _readOnlyDates =
    new ReadOnlyCollection<Date>(_dates);

public ReadOnlyCollection<Date> Dates
{
    get { return _readOnlyDates; }
}

Both are basically the same because of how .NET compiles automatic properties. 由于.NET如何编译自动属性,因此两者基本上是相同的。 Automatic properties became available with .NET 3.5. .NET 3.5提供了自动属性。

They are equivalent in the internal compiled form, except that you cannot access the compiler generated private variable in the second form. 它们在内部编译形式中是等效的,除了您不能以第二种形式访问编译器生成的私有变量。

From a code efficiency point of view, they are equivalent as well, the just in time compiler normally directly accesses the private variable without the overhead of calling an access function (after the runtime environment has checked accessibility etc.). 从代码效率的角度来看,它们也是等效的,即时编译器通常直接访问私有变量,而没有调用访问函数的开销(在运行时环境检查了可访问性之后)。

From a coding perspective, I prefer the second version which is more compact (less to write, less to read). 从编码的角度来看,我更喜欢第二个版本,它更紧凑(更少的编写,更少的阅读)。

The second syntax was introduced in C# 3.0. 第二种语法在C#3.0中引入。 So the first variant would be more compatible to old compilers. 因此,第一种变体将与旧编译器更兼容。

I tend to use auto properties more because a property is a good way to express intent about what your object is doing, but still have some protection. 我倾向于更多地使用自动属性,因为属性是表达您的对象正在执行的操作的一种好方法,但仍然具有一定的保护作用。

Almost all of my property declarations look like: 我几乎所有的属性声明如下:

public bool IsBlah { get; private set; }

This makes it a nice, readable, and protected getter. 这使其成为一个不错的,可读的和受保护的吸气剂。

But there are times when you want an explicit backing field: 但是有时您需要显式的后备字段:

private bool? _isBlah;
public bool IsBlah
{
    get
    {
        if (_isBlah == null)
        {
            // Do something expensive here and set _isBlah
            _isBlah = true;
        }
        return _isBlah;
    }
}

The former is the original approach, the latter is an example of the newer 'auto properties' facility whereby the compiler generates a backing field for you automatically. 前者是原始方法,后者是较新的“自动属性”功能的示例,编译器通过该功能自动为您生成一个后备字段。

Some people (myself included) shy away from auto properties because the syntax is easy to mistake for abstract properties, there is no facility for 'readonly' properties and the syntax for auto properties with private setters is clumsy: 有些人(包括我自己)回避自动属性,因为语法很容易被误认为抽象属性,没有用于“只读”属性的功能,并且带有私有设置器的自动属性的语法很笨拙:

public List Dates
{
    get;
    private set;
}

I also find it uncomfortable to have my classes' internal implementation accessing fields via the class API. 我还发现让类的内​​部实现通过类API访问字段很不舒服。

The second variation is know as auto-implemented properties and was introduced in C#3.0 (hence why you may not have encountered it before). 第二种变化称为自动实现的属性 ,是C#3.0中引入的(因此您以前可能没有遇到过这种情况)。

It is preferable to use this format if you want to create simple properties with backing-fields and don't need to implement any logic in the 'getter' and 'setter'. 如果要创建具有后备字段的简单属性并且不需要在“ getter”和“ setter”中实现任何逻辑,则最好使用此格式。 Not only is it more concise, but it also forces you to access the property directly, rather than going through the backing field, which is normally best practice. 它不仅更加简洁,而且还迫使您直接访问该属性,而不是通过通常是最佳实践的背景进行访问。

Note you can still initialise properties, you just do it via the constructor. 注意,您仍然可以初始化属性,只需通过构造函数即可。

public class MyClass
{

  public List<Date> Dates
  {
      get;        
      set;    
  }

  public MyClass()
  {
      Dates = new List<Date>();
  }

}

I personally prefer the first method as it allows you to perform a few operations prior to the return. 我个人更喜欢第一种方法,因为它允许您在返回之前执行一些操作。

EG (A really poor example) EG(一个非常糟糕的例子)

    private int _limit;
    private int _onHand;
    private bool returnToVendor;

    public Item(int limit, int onHand)
    {
       _limit = limit;
       _onHand = onHand;
    }

    public int ReturnStock
    {
       get
       {
         if(_onHand > _limit)
         {
            returnToVendor = true;
            return _onHand;
         }
       }

       set
       {
           _onHand = value;

           if(_onHand < _limit)
           {
              returnToVendor = false;
           }
       }
    }

It doesn't matter. 没关系 The second is just sugar. 第二个就是糖。 I always use the second because it's cleaner, but every once in a while I need access to the backing value. 我总是使用第二个,因为它更干净,但是我偶尔需要访问支持值。

As long as you don't have to make sure the List<Date> is initialized in the getter you are fine with both versions. 只要您不必确保在getter中初始化List<Date>就可以使用这两个版本。 I just suggest that you are using one version and you don't mix it in your code... 我只是建议您使用一个版本,并且不要在代码中混用它。

If you need it initialized you have to go for the first version... 如果需要初始化,则必须使用第一个版本...

private List<Date> _dates; 

public List<Date> Dates 
{ 
    get { if (_dates == null) _dates = new List<Date>(); return _dates; } 
    set { _dates = value; } 
} 

I believe they compile to the same code. 我相信它们可以编译为相同的代码。 The latter is just syntactic sugar to represent the former. 后者只是表示前者的语法糖。 I tend to think of the latter as a placeholder for future logic that may need to be placed in the properties, at which point I'd convert said affected properties to the former. 我倾向于将后者视为将来逻辑的占位符,可能需要将其放置在属性中,此时,我将把受影响的属性转换为前者。

The two are compiled roughly the same way (I don't know that the backing field's name would specifically be the same, but they'd be functionally equivelant). 两者的编译方式大致相同(我不知道背景字段的名称将完全相同,但在功能上是等同的)。

IIRC, the ability to do Automatic Properties ( public List<Date> Dates {get; set;} ) was added in either .NET 3.0 or 3.5. IIRC在.NET 3.0或3.5中添加了执行自动属性( public List<Date> Dates {get; set;} )的功能。

As far as I can remember, I have always managed my list properties from within my object, making them readonly. 据我所记得,我一直在对象内部管理列表属性,使它们成为只读。

private IList<DateTime> _dates;

public MyClass() {
    _dates = new List<DateTime>();
}

public IList<DateTime> Dates {
    get {
        return _dates;
    }
}

By doing so, I assure that my list is never null when I access it, since the client cannot assign it. 这样,我确保我访问列表时永远不会为空,因为客户端无法分配它。

However, for your example, you only need to use the former approach if you need some kind of logic when getting or setting a property. 但是,对于您的示例,仅在获取或设置属性时需要某种逻辑时才需要使用前一种方法。 Otherwise, automatic properties does exactly the same you would, only getting and setting a value to a private field. 否则,自动属性的作用与您完全相同,只是获取并设置一个私有字段的值。 Furthermore, the { get; set; } 此外, { get; set; } { get; set; } { get; set; } improves readability and helps other programmers understand your intention, in my humble point of view. { get; set; }以我的谦卑观点,可以提高可读性并帮助其他程序员理解您的意图。

For instance: 例如:

public class MyClass {
    private IList<DateTime> _dates;

    public IList<DateTime> Dates {
        get {
            return _dates;
        } set {
            _dates = value;
        } 
    }
}

versus

public class MyClasse {
    public IList<DateTime> Dates { get; set; }
}

The second way makes it leaner and swifter, at least to me, what the intention is. 第二种方法至少对我而言使意图更精简和快捷。 And it becomes faster to code a class, when no logic inside the getter and setter is necessary. 当不需要在getter和setter内部使用逻辑时,编写类的代码将变得更快。

Otherwise, one is not better than the other and does quite the same, speaking of getting and setting simply the property's value with no logic. 否则,一个不比另一个更好,并且做得完全一样,说到获取和设置该属性的值而没有逻辑。

Most importantly, you need to be comfortable with your code. 最重要的是,您需要熟悉您的代码。 If it ends for you not getting any improvements, and you like what you're doing, than just do it. 如果最终结果是您没有获得任何改进,并且您喜欢自己在做什么,那么就不仅仅要做。 =) =)

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

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