【问题标题】:Encapsulation C# newbie封装 C# 新手
【发布时间】:2013-07-16 02:55:26
【问题描述】:

C# 新手,我知道封装只是“保护数据”的一种方式。但我仍然不清楚。我认为 get 和 set 访问器的 point 是在这些方法中添加测试,以检查参数是否符合特定标准,然后允许外部函数获取和设置任何内容,如下所示:

private string myName;
public string MyName;// this is a property, speical to c#, which sets the backing field.

private string myName = "mary";// the backing field.

public string MyName // this is a property, which sets/gets the backing field.
{
    get
    {
        return myName;
    }
    set
    {
        if (value != "Silly Woman"){ 
           myName = value;
        }

    } 
}

但我在 c# 中看到的代码看起来像这样:

public string MyName { get; set; }

为什么你只需要一个 get 和 set,里面什么都没有,这不就和把你的私有支持字段声明为 public 一样吗?如果你可以从外部获取和设置它,你为什么不直接做呢?

【问题讨论】:

    标签: c# get set encapsulation


    【解决方案1】:

    确实,创建一个自动属性如下:

    public string Name { get; set; }
    

    与构建由字段支持的属性相同:

    private string _name;
    public string Name {
        get { return _name; }
        set { _name = value; }
    }
    

    这些属性的重点不是隐藏数据。正如您所观察到的,他们不这样做。相反,这些属性可以做其他事情,而不仅仅是使用字段:

    public string Name {
        get { return _name; }
        set { if (value == null) throw new Exception("GTFO!"); _name = value; }
    }
    

    还有一点,你可以让属性虚拟

    public virtual string Name { get; set; }
    

    如果被覆盖,它可以在派生类中提供不同的结果和行为。

    【讨论】:

    • 这是 5 个绝对精彩的答案。谢谢大家!
    • 写答案的好方法!
    【解决方案2】:

    通过使用public string MyName { get; set; },您可以在以后更改其逻辑,而无需重新编译/更改使用您的属性的其他代码。

    例如,如果您正在创建一个库并且 v1 使用一个字段而 v2 使用一个属性,则使用 v1 的应用程序将无法在不重新编译的情况下使用 v2(并且,如果它们是用某些 .NET 编写的,则可能会更改代码访问字段的语法不同的语言)。

    另一个重要的区别是在序列化场景中——其中很多不支持字段。此外,任何需要属性的接口都无法在不使用属性的情况下实现,但根据接口的不同,可能不需要在其中进行任何额外的检查/逻辑。

    【讨论】:

      【解决方案3】:

      它使以后添加逻辑变得更加容易。如果您的类具有要更改为属性的公共字段,则必须重新编译使用您的类的所有内容。这是我最初不理解的关键点。

      如果你有课:

      public class MyClass
      {
          public string MyString;
      }
      

      您可以像这样访问该值:

      var myClass = new MyClass();
      string s = myClass.MyString;
      

      现在将其更改为属性:

      public class MyClass
      {
          public string MyString { get; set; }
      }
      

      如何访问它?完全相同的方式:

      var myClass = new MyClass();
      string s = myClass.MyString;
      

      所以没什么大不了的,对吧?嗯,其实……

      属性实际上被编译成getter和setter方法:

      get_MyString()set_MyString(string value)

      所以这两种方法确实会产生不同的编译代码。现在,如果你所有使用这个类的代码都在同一个项目中,那没什么大不了的,因为它们都会一起编译。但是,如果您有一个已分发的 API 库,则更新可能会大得多。

      【讨论】:

        【解决方案4】:

        因为如果您想稍后添加检查/测试,更改代码会更容易。 尤其是如果您的代码中有很多继承和很多类,则很难将实现从公共变量更改为公共属性。

        此外,您可以向属性中的 get 和 set 添加不同的属性,例如如果您使用反射。属性的 get 和 set 是内部不同的方法。如果您只有一个公共变量/字段,则无法为不同的访问方式添加不同的属性。

        【讨论】:

          【解决方案5】:

          是的,但您可以轻松地将其更改为:

          public string MyName { get; private set; }
          

          另外,属性用于其他场景,如DataContracts 和序列化......所以,这是一个很好的功能......(主要是语法糖。我认为)编辑:我收回......你可以对它应用virtual,所以就不一样了

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-11-18
            • 1970-01-01
            相关资源
            最近更新 更多