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

C# 为什么我们要在类中创建一个私有变量,然后设置属性?,c#,.net,class,oop,C#,.net,Class,Oop,为什么我们要在类中创建一个私有变量,然后在c#中的下面几行中将其作为公共属性? 此外,我不了解获取和设置属性的概念 我是说我们为什么要这样做 public class MyClass { private string _myProperty; public string MyProperty { get { return _myProperty; } set

为什么我们要在类中创建一个私有变量,然后在c#中的下面几行中将其作为公共属性? 此外,我不了解获取和设置属性的概念

我是说我们为什么要这样做

 public class MyClass
    {
        private string _myProperty;

        public string MyProperty
        {
           get
           { return _myProperty; }
           set
           { _myProperty = value; }
    }
还是这个

public class MyClass
{
    public string MyProperty {get;set;}
}
我的问题与此非常相似:

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

  • 为什么要先创建私有变量,然后从中生成公共属性?为什么不迈出一步呢
  • 我们需要什么“获取”和“设置”?为什么使用两种方法,有什么区别
这个问题的答案可能太长了。但是,即使你花宝贵的时间只是为了恰当地解释一点,我也将不胜感激。提前感谢:)

为什么要先创建私有变量,然后再从中生成属性 信息技术为什么不迈出一步呢

当您想在设置属性之前进行某种验证,或者基本上抽象出类中与该属性相关的内容时,可以使用私有变量。例如,如果希望给定变量在某个范围内:

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

        foo = value;
    }
}
private int foo;
公共int-Foo
{
获取{return foo;}
设置
{
如果(值<0 | |值>10)
{
抛出新ArgumentOutOfRangeException(值);
}
foo=价值;
}
}
我们需要什么“获取”和“设置”,为什么需要两种方法来使用它

C#-3.0带来了,因为MSFT看到很多人使用属性是为了“有一天我可能想验证我的变量或更改内部实现”。通过公开属性而不是变量,可以在以后添加任何代码验证,而不会破坏与属性的任何调用方的现有“契约”

@JonSkeet拼得很好,直截了当(谢谢@Sriram):

  • 还有更细粒度的属性访问控制
  • 需要公开获取,但真的只需要设置受保护的访问吗?没问题(至少从C#2开始)
  • 要在值更改时中断调试器吗?只需在setter中添加一个断点
  • 要记录所有访问权限吗?只需将日志添加到getter
  • 属性用于数据绑定;字段不是

你的两个例子是等价的。第二个是第一个的语法糖

属性的原因是在类的内部状态上创建抽象。例如,如果您使用公共字段,则在不更改类的接口的情况下,您没有机会更改它。使用属性可以隐藏实现,对于代码的其余部分,不会更改任何内容。 例如:

我想更改实现细节,以便直接从db存储/检索值

public class MyClass
{
    public string MyProperty {
        get{_db.GetValue('myFiled');}
        set{_db.SetValue('myField', value)}}
}

正如您所看到的,实现发生了巨大的变化,但是类接口仍然是一样的。

类的内部逻辑应该从外部保持隐藏
假设您需要一个可以从外部访问但只能从类内部设置的字段,而不需要属性,则必须执行以下操作:

public class Example
{
   private String _data;

   public String GetData()
   {
      return _data;
   }
}
对于属性,您可以通过以下方式执行相同的操作:

public class Example
{
   private String _data;

   public String Data { get; private set}       

}
您可以缩短代码并使其更干净,您可以完全控制字段的可访问性,但是属性有很多优点。例如,假设您的私有字段需要一些逻辑,假设在指定字段之前从外部访问属性<考虑下面的例子:

public class Example
{
   private MyCustomClass _data;

   public MyCustomClass Data { get { return _data }; private set { _data = value;}}       

}
如果尚未分配_数据,则如果您尝试使用它,代码中的某个地方将出现空异常,但您可以实现一些逻辑来避免它,如下所示:

public class Example
{
   private MyCustomClass _data;

   public MyCustomClass Data
   { 
      get
      {
         if(_data == null)
           _data = new MyCustomClass();
         return _data;
      }
      private set { _data = value;} }             
}
public class Example
{
   private String _myData;
   public String MyData{ get {return _myData}; set { _myData = value}}
}
因此,您可以使用属性实现逻辑。

此外,请记住,当您创建这样的属性时

public class Example
{
   public String MyData{ get; set;}
}
实际上,当您编译它时,编译器会将其转换为如下内容:

public class Example
{
   private MyCustomClass _data;

   public MyCustomClass Data
   { 
      get
      {
         if(_data == null)
           _data = new MyCustomClass();
         return _data;
      }
      private set { _data = value;} }             
}
public class Example
{
   private String _myData;
   public String MyData{ get {return _myData}; set { _myData = value}}
}


最后,假设在将来您需要更改该字段设置值的逻辑,如果您使用公共字段,您将有很多工作要做,但是如果您使用属性,您只需要更改属性的逻辑,这样做了,可维护性也是一个很好的属性支持!

编辑

关于绑定我不太清楚大多数框架使用属性来绑定prupose

将字段设置为私有并将其作为属性公开给类提供了控制set和get操作的能力,这在不同的场景中很有用

验证 类可以在将提供的数据存储到字段之前验证数据:

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();
             }
         }
      }
      ..
      ..
}
不提供setter,或限制对setter的访问 使用属性而不是字段的另一个好处是,它允许对象限制对字段的访问。在前面的示例中,我们有一个没有setter的方法。这种方法的另一个用途是限制对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);
      }
      ..
      ..
}
如您所见,这种方法的好处是,当属性从类内部更改时,它允许类执行一些操作

提高活动 用于引发XXChanged事件的常见模式是检查setter中的值,并在事件发生更改时引发事件:

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);
         }
    }
}
这种方法的另一个常见用途是实现接口

无逻辑模型 即使您不需要任何属性可以实现的功能,并且您拥有一个无逻辑类,但最好的做法是不将类字段公开给类的外部世界。在这种情况下,您可以简单地使用“自动特性”作为遵循最佳实践的快捷方式,而无需直接定义字段

class UserModel {
      public string Username {
           get;
           set;
      }
      public DateTime Birthdate {
           get;
           set;
      }
      ..
      ..
}

事实上,谷歌可以很容易地回答这个问题,这里有一个stackoverflow的答案:GoodQue