代码之家  ›  专栏  ›  技术社区  ›  Amr

在C中使用私有财产有什么原因吗?

  •  203
  • Amr  · 技术社区  · 7 年前

    我刚意识到# 属性构造 也可以与 私有的 访问修饰符:

    private string Password { get; set; }
    

    虽然这在技术上很有趣,但我无法想象什么时候使用它,因为 私人领域 牵连 少仪式 :

    private string _password;
    

    我无法想象什么时候我需要在内部 得到 但不是 设置 设置 但不是 得到 私有字段:

    private string Password { get; }
    

    private string Password { set; }
    

    但是也许有一个用例 嵌套/继承类 或者在get/set可能包含的位置 逻辑 虽然我倾向于保持属性的严格简单性,并让显式方法做任何逻辑,例如,不要只返回属性的值。 GetEncodedPassword() .

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

    补遗

    很好的答案,通过阅读我挑选了这些私人财产的用途:

    • 当需要延迟加载私有字段时
    • 当私有字段需要额外的逻辑或是计算值时
    • 因为私有字段很难调试
    • 为了“向自己呈现一份合同”
    • 在内部转换/简化公开属性作为序列化的一部分
    • 包装要在类中使用的全局变量
    14 回复  |  直到 8 年前
        1
  •  181
  •   Shaun Bowe    14 年前

    如果我需要缓存一个值,并且希望懒惰地加载它,我就使用它们。

    private string _password;
    private string Password
    {
        get
        {
            if (_password == null)
            {
                _password = CallExpensiveOperation();
            }
    
            return _password;
        }
    }
    
        2
  •  117
  •   Eric Lippert    16 年前

    在我的代码中,这一点的主要用法是惰性初始化,正如其他人所提到的。

    字段上私有属性的另一个原因是私有属性比私有字段更容易调试。我经常想知道“这个字段是意外设置的;谁是设置这个字段的第一个调用方?”如果你只需要在二传手上放一个断点,然后点击Go,这就简单多了。你可以把日志放在那里。您可以将性能指标放在其中。可以放入在调试版本中运行的一致性检查。

    基本上可以归结为: 代码远比数据强大 . 任何能让我编写我需要的代码的技术都是很好的。字段不允许在其中编写代码,属性允许。

        3
  •  37
  •   Reed Copsey    16 年前

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

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

    如果我觉得一个属性最终可能需要额外的逻辑,我有时会将它包装成一个私有属性,而不是使用一个字段,只是为了以后不必更改代码。


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

    public string Password 
    {
        get; 
        private set;
    }
    

    这会给你一个公开的getter,但会保持setter是私有的。

        4
  •  19
  •   Alex Dresko    11 年前

    惰性初始化是一个可以保持整洁的地方,例如

    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;
    

    然后你可以写: this.MyType 无处不在,而不是 this.mytype.Value 并且封装了一个事实,即它在一个地方被懒散地实例化。

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

        5
  •  17
  •   JaredPar    16 年前

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

        6
  •  12
  •   Lukasz Madon    16 年前

    我唯一能想到的用法

    private bool IsPasswordSet 
    { 
         get
         {
           return !String.IsNullOrEmpty(_password);
         }
    }
    
        7
  •  8
  •   Matt Greer    16 年前

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

    就像你用财产向你的消费者展示一份关于什么是你的类的合同一样,你也可以以非常相似的理由向你自己展示一份合同。所以是的,我确实在有意义的时候使用私有财产。有时,私有属性可以隐藏实现细节,例如延迟加载、属性实际上是多个字段和方面的聚集,或者属性需要在每次调用时进行虚拟实例化(想想 DateTime.Now )有时甚至在类的后端对自己强制执行这个命令也是有意义的。

        8
  •  7
  •   Marc Gravell    16 年前

    我在序列化中使用它们,比如 DataContractSerializer 或支持此用法的protobuf net( XmlSerializer 不)。如果需要将对象简化为序列化的一部分,则此功能非常有用:

    public SomeComplexType SomeProp { get;set;}
    [DataMember(Order=1)]
    private int SomePropProxy {
        get { return SomeProp.ToInt32(); }
        set { SomeProp = SomeComplexType.FromInt32(value); }
    }
    
        9
  •  6
  •   Earlz    16 年前

    我一直在做的一件事是将“全局”变量/缓存存储到 HttpContext.Current

    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;
      }
    }
    
        10
  •  5
  •   Hans Olsson    16 年前

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

    如果以后需要以某种方式更改数据类型,或者需要使用反射,也可以使用反射。

        11
  •  5
  •   Yohanes Nurcahyo    11 年前

    我使用私有属性来减少访问经常使用的子属性的代码。

        private double MonitorResolution
        {
            get { return this.Computer.Accesories.Monitor.Settings.Resolution; }
        }
    

    如果有许多子属性,它是有用的。

        12
  •  2
  •   corsiKa    16 年前

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

        13
  •  2
  •   Marc    16 年前

    当存在与属性集或get关联的逻辑(想想懒惰的初始化)并且该属性在类中的一些地方被使用时,这是完全有意义的。

    如果只是一个直接的后场?没有什么能成为一个好理由。

        14
  •  0
  •   Lucas Martins Juviniano    8 年前

    嗯,正如没有人提到的,您可以使用它来验证数据或锁定变量。

    • 验证

      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;
              }
          }
      }
      

      注意:锁定引用时,不会锁定对被引用对象成员的访问。

    懒惰的引用:当懒惰的加载时,您可能最终需要进行异步操作,而现在已经有了。 AsyncLazy . 如果您使用的是比Visual Studio SDK 2015更旧的版本或不使用它,也可以使用 AsyncEx's AsyncLazy .