为什么我们在类中创建一个私有变量然后设置属性?

Aks*_*hay 9 .net c# oop class

为什么我们在类中创建一个私有变量,然后在c#中的以下行中创建一个公共属性?我也没有得到获取和设置属性的概念.

我的意思是为什么我们这样做

 public class MyClass
    {
        private string _myProperty;

        public string MyProperty
        {
           get
           { return _myProperty; }
           set
           { _myProperty = value; }
    }
Run Code Online (Sandbox Code Playgroud)

或这个

public class MyClass
{
    public string MyProperty {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

我的问题与此问题非常类似: 为什么我们需要创建类变量来获取和设置属性?

上面的线程似乎没有解决我的问题.有人请详细说明:

  • 为什么首先创建私有变量然后从中创建公共属性?为什么不一步?
  • 我们需要什么'获得'和'设置'?为什么两种方法使用它,有什么区别?

问题的答案可能太长了.但即使你花费宝贵的时间来恰当地解释一个问题,我也不仅仅是有义务.提前致谢 :)

Yuv*_*kov 7

为什么首先创建私有变量然后从中创建属性?为什么不一步?

如果要在设置属性之前进行某种验证,则使用私有变量,或者基本上抽象出类中有关该属性的内容.例如,如果您希望给定变量在一个范围内:

private int foo;
public int Foo 
{
    get { return foo; }
    set 
    {
        if (value < 0 || value > 10)
        {
            throw new ArgumentOutOfRangeException(value);
        }

        foo = value;
    }
}
Run Code Online (Sandbox Code Playgroud)

我们需要什么'获得'和'设置'以及为什么有两种方法可以使用它?

C#-3.0带来了自动属性,因为MSFT看到很多人使用属性"有一天我想要验证我的变量或改变内部实现的可能性".公开属性而不是变量允许您稍后添加任何代码验证,而不会破坏与属性的任何调用者的现有"契约".

@JonSkeet很好地拼凑出来,在他的C#In Depth中表现平平(谢谢@Sriram):

  • 有更多细粒度的访问控制和属性.
  • 需要它是公开可获得的,但实际上只希望它设置为受保护的访问?没问题(从C#2开始,至少).
  • 想要在值发生变化时闯入调试器?只需在setter中添加断点即可.
  • 想记录所有访问权限?只需将日志记录添加到getter即可.
  • 属性用于数据绑定; 字段不是.


Meh*_*raz 6

将字段设为私有并将其作为属性公开可提供控制设置和获取操作的类权限,这在不同情况下很有用。

验证方式

The class can validate provided data before storing it into the field:

class WeatherInfo {
      private static readonly int minDegree = -273;
      private static readonly int maxDegree = 75;
      private int degree;
      public int Degree {
         get {
             return this.degree;
         }
         set {
             if (value < minDegree || value > maxDegree) {
                 throw new ArgumentOutOfRangeException();
             }
         }
      }
      ..
      ..
}
Run Code Online (Sandbox Code Playgroud)

Invalid field value

In some circumstances, a field of an object may not have a meaningful value. Providing a getter method, allows the object to inform it's client about that.

class User {
    private DateTime loginTime;
    private bool loggedIn;
    ..
    ..
    public DateTime LoginTime {
        get {
            if (!this.loggedIn) {
               throw new InvalidOperationException();
            }
            return loginTime;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Not providing a setter, or limiting access to the setter

Another benefit of using properties instead of fields is that it allows the object to limit access to the field. In the previous example we had a method without a setter. Another use of this approach is limiting access to the setter.

class Customer {
      private string name;
      private string family;
      private string nameFamily;

      public string name {
           get {
               return this.name;
           }
           private set {
               if (!string.Equals(name, value)) {
                    this.name = value;
                    this.UpdateNameFamily();
               }
          }
      }
      private void UpdateNameFamily() {
          this.nameFamily = string.Format("{0} {1}", this.name, this.family);
      }
      ..
      ..
}
Run Code Online (Sandbox Code Playgroud)

as you can see, the benefit of this approach is it allows the class to perform some action when the property gets changed from inside of the class.

Raising events

A common pattern used to raise XXXXChanged events is checking the value in the setter and raise a event if it is changed:

class Question {
    public event EventHandler AnsweredChanged;
    private bool isAnswered;
    ..
    ..
    public bool IsAnswered {
        get {
            return this.isAnswered;
        }
        set {
            if (this.isAnswered != value) { 
                this.OnIsAnsweredChanged();
            }
        }
    }
    private void OnIsAnsweredChanged() {
         if (this.AnsweredChanged!= null) {
              this.AnsweredChanged(this, EventArgs.Empty);
         }
    }
}
Run Code Online (Sandbox Code Playgroud)

Another common use of this approach is implementing INotifyPropertyChanged interface.

Logic-less models

Even if you don't need none of what can be achieved by properties, and you have a logic-less class it has been a best practice to not to expose class fields to outside world of the class. In that case, you can simply use auto-properties as the shortcut way to follow the best practice, without directly defining a field.

class UserModel {
      public string Username {
           get;
           set;
      }
      public DateTime Birthdate {
           get;
           set;
      }
      ..
      ..
}
Run Code Online (Sandbox Code Playgroud)