是否有任何理由在C#中使用私有属性?

是否有任何理由在C#中使用私有属性?,c#,properties,access-modifiers,C#,Properties,Access Modifiers,我刚刚意识到C#属性构造也可以与私有访问修饰符一起使用: private string Password { get; set; } 虽然这在技术上很有趣,但我无法想象何时我会使用它,因为私人领域涉及的仪式更少: private string _password; 我无法想象何时我需要在内部获取但不设置或设置但不获取一个私有字段: private string Password { get; } 或 但是可能存在嵌套/继承类的用例,或者get/set可能包含逻辑,而不只是返回属性的值,尽管

我刚刚意识到C#属性构造也可以与私有访问修饰符一起使用:

private string Password { get; set; }
虽然这在技术上很有趣,但我无法想象何时我会使用它,因为私人领域涉及的仪式更少:

private string _password;
我无法想象何时我需要在内部获取但不设置设置但不获取一个私有字段:

private string Password { get; }

但是可能存在嵌套/继承类的用例,或者get/set可能包含逻辑,而不只是返回属性的值,尽管我倾向于保持属性严格简单,并让显式方法执行任何逻辑,例如
GetEncodedPassword()

是否有人出于任何原因在C#中使用私有属性,或者它只是技术上可能但在实际代码构造中很少使用的属性之一?

补遗 答案很好,通过阅读,我挑选了这些私人物业的用途:

public string Password 
{
    get; 
    private set;
}
  • 当需要延迟加载私有字段时
  • 当私有字段需要额外逻辑或是计算值时
  • 因为私有字段可能很难调试
  • 为了“向自己展示合同”
  • 将公开属性作为序列化的一部分进行内部转换/简化
  • 包装要在类中使用的全局变量

    • 我时不时地使用它们。当您可以轻松地在属性中设置断点或添加日志语句等时,它们可以使调试变得更容易

      如果以后需要以某种方式更改数据的类型,或者需要使用反射,此功能也很有用

      可能存在嵌套/继承类的用例,或者get/set可能包含逻辑,而不只是返回属性的值

      即使我不需要属性的getter或setter上的逻辑,我个人也会使用它。使用属性,甚至是私有属性,确实有助于将来验证代码,以便以后在需要时可以将逻辑添加到getter

      如果我觉得某个属性最终可能需要额外的逻辑,我有时会将其包装到私有属性中,而不是使用字段,这样以后就不必更改代码了


      在一个半相关的案例中(尽管与您的问题不同),我经常在公共财产上使用私人设定者:

      public string Password 
      {
          get; 
          private set;
      }
      

      这提供了一个公共getter,但保持setter私有。

      通常只使用get/set方法修改成员,即使是私有方法。现在,这背后的逻辑是,你知道你的get/set总是以一种特殊的方式运行(例如,触发事件),这似乎是没有意义的,因为这些不会包含在属性方案中。。。但是旧习惯很难改掉。

      当属性set或get(想想惰性初始化)有逻辑关联,并且该属性在类中的一些地方使用时,这是非常有意义的


      如果只是一个直背场?我脑子里没有什么好理由。

      我能想到的唯一用法

      private bool IsPasswordSet 
      { 
           get
           {
             return !String.IsNullOrEmpty(_password);
           }
      }
      

      属性和字段不是一对一的。属性是关于类的接口(不管是关于它的公共接口还是内部接口),而字段是关于类的实现。属性不应被视为仅公开字段的方式,而应被视为公开类的意图和用途的方式


      就像您使用属性向消费者展示关于类的构成的契约一样,您也可以出于非常类似的原因向自己展示契约。所以,是的,我确实在有意义的时候使用私有财产。有时,私有属性可以隐藏实现细节,如延迟加载、属性实际上是多个字段和方面的聚合,或者属性需要在每次调用时进行虚拟实例化(想想
      DateTime.Now
      )。在某些情况下,即使在类的后端对自己强制执行此操作也是有意义的。

      惰性初始化是一个可以使它们整洁的地方,例如

      private Lazy<MyType> mytype = new Lazy<MyType>(/* expensive factory function */);
      
      private MyType MyType { get { return this.mytype.Value; } }
      
      // In C#6, you replace the last line with: private MyType MyType => myType.Value;
      
      private Lazy mytype=new Lazy(/*昂贵的工厂函数*/);
      私有MyType MyType{get{返回this.MyType.Value;}}
      //在C#6中,将最后一行替换为:private MyType MyType=>MyType.Value;
      
      然后,您可以在任何地方编写:
      this.MyType
      而不是
      this.MyType.Value
      ,并封装它在单个位置惰性实例化的事实


      遗憾的是,C#不支持将支持字段范围限定到属性(即在属性定义中声明它),以完全隐藏它并确保只能通过属性访问它。

      如果需要缓存值并希望延迟加载它,我会使用它们

      private string _password;
      private string Password
      {
          get
          {
              if (_password == null)
              {
                  _password = CallExpensiveOperation();
              }
      
              return _password;
          }
      }
      

      私有get-only属性的一个好用法是计算值。有好几次,我的属性是私有的只读属性,并且只对我类型中的其他字段进行计算。它不值得一个方法,也不值得其他类感兴趣,所以它是私有属性。

      正如其他人所提到的,在我的代码中,它的主要用途是延迟初始化

      字段上使用私有属性的另一个原因是,私有属性比私有字段更容易调试。我经常想知道诸如“此字段意外设置;谁是设置此字段的第一个调用方?”之类的事情,如果您只需在setter上设置一个断点并点击go键,那么就更容易了。你可以把日志放在那里。您可以将性能指标放在其中。您可以放入在调试生成中运行的一致性检查

      基本上,它归结为:代码远比数据强大。任何让我编写所需代码的技术都是好的。Fi
      public SomeComplexType SomeProp { get;set;}
      [DataMember(Order=1)]
      private int SomePropProxy {
          get { return SomeProp.ToInt32(); }
          set { SomeProp = SomeComplexType.FromInt32(value); }
      }
      
      private static string SomeValue{
        get{
          if(HttpContext.Current.Items["MyClass:SomeValue"]==null){
            HttpContext.Current.Items["MyClass:SomeValue"]="";
          }
          return HttpContext.Current.Items["MyClass:SomeValue"];
        }
        set{
          HttpContext.Current.Items["MyClass:SomeValue"]=value;
        }
      }
      
          private double MonitorResolution
          {
              get { return this.Computer.Accesories.Monitor.Settings.Resolution; }
          }
      
      string _password;
      string Password
      {
          get { return _password; }
          set
          {
              // Validation logic.
              if (value.Length < 8)
              {
                  throw new Exception("Password too short!");
              }
      
              _password = value;
          }
      }
      
      object _lock = new object();
      object _lockedReference;
      object LockedReference
      { 
          get
          {
              lock (_lock)
              {
                  return _lockedReference;
              }
          }
          set
          {
              lock (_lock)
              {
                  _lockedReference = value;
              }
          }
      }
      
      private MyAggregateClass _mac;
      
      private MyAggregateClass Mac
      {
          get => _mac;
          set
          {
              if(value == _mac) return;
              _mac = value;
              PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(DisplayInfo)));
          }
      }
      
      public string DisplayInfo => _mac.SomeStringInformationToDisplayOnUI;
              
      
      private void SetMac(MyAggregateClass newValue)