为什么我需要通过公共财产公开的私人领域?

时间:2010-01-27 21:41:56

标签: c# properties

我主要来自Java世界。所以,C#属性看起来不错。

我知道使用C#3.0或更高版本我可以使用自动属性。我更喜欢它:)。

我的问题是关于一个(可能更旧的)代码,我可以看到这个:

   private int age;

   public int Age {

     get { return age; }
     set { age = value; }     
   }

为什么我需要私人领域时代?我真的藏在这里的是什么?

编辑:

我完全理解对getter和setter的需求。我提到我是从Java世界来的,并且一直这样做。

我明白C#3.0或以上的自动属性是合成糖。但也许我的问题有一个更简单的答案。这是否意味着(低于C#3.0)该财产没有任何价值。那么它必须从其他领域获得价值吗?

11 个答案:

答案 0 :(得分:3)

旧版本的C#没有自动属性,因此您必须声明属性所执行的变量,如示例中所示。这些天,相同的代码可以表示为:

public int Age { get; set; }

我认为这可以回答你的问题。但是,如果你问“为什么不公开int Age;并且让程序员直接在字段上设置值?”,那么:

首先要记住的是,属性访问器被编译为方法。这意味着它具有不同的ABI,而不仅仅是读/写到类成员​​变量,即使它在语法上看起来与您拥有的相同:

class Fu {
  public int Age;
}

所以,这意味着,如果在某个时刻,您需要添加一些Age字段已更改的通知 - 如果您使用的是属性,则可以轻松地将此通知逻辑添加到属性设置器中打破ABI。

public int Age {
  get { return age; }
  set { age = value; NotifySomeOtherCode (); }
}

如果您从公共字段开始,稍后将其更改为属性将更改ABI,这对可能取决于您的程序集的任何程序都是不利的。所以最好从属性开始。

希望我有意义......

答案 1 :(得分:2)

旧版本的C#编译器不支持自动属性。

上面的代码或多或少与此相同(假设该字段实际上从未直接使用过):

public int Age {
  get;
  set;
}

答案 2 :(得分:1)

在这种情况下,您不需要它。但是,如果您需要在setter或getter中执行任何其他操作,则自动属性将不起作用 - 您需要使用私有字段进行操作。

答案 3 :(得分:1)

C#中的自动属性在编译时,在功能上与上面的代码完全相同。编译器为您生成一个支持字段。

所以你需要需要一些支持属性的东西 - 一个字段或一些代码 - 它只是用自动属性的快捷方式为你照顾。

答案 4 :(得分:1)

沼泽标准的答案是“封装年龄存储方式和位置的实施细节”。

出于检索目的,一个更现实的例子可能是,有一天,您可能希望以一种意味着直接访问不太好的方式访问该值。例如,如果它是您可能在其他地方缓存的值,或者它是计算值。

在封装设置过程方面,它意味着您可以将一些模型级验证嵌入到setter中;如果有人试图设置概念上无效的值,您可以抛出IllegalArgumentException并拒绝它。

在这些情况下,封装意味着您不必更改所有现有代码,因为您必须将值包装在某些内容中。

答案 5 :(得分:0)

属性只是编写一对 get set 方法的好方法。在Java中你会这样做:

private int age;

public int getAge() { return age; }
public void setAge(int value) { age = value; }

您需要私有字段来存储某个年龄 - getAge和setAge只是方法。

同样适用于C#到3.0之前的版本:

private int age;

public int Age
{
   get { return age; }
   set { age = value; } 
}

这是一个get和set方法,很好地配对,因此您可以编写x.Age = 21而不是x.setAge(21)

使用自动属性,C#编译器会为您生成私有字段(但它仍然存在!):

public int Age
{
   get;
   set;
}

自动属性的好处是您不必再自己手动创建支持字段。

手动版本的好处是,您可以为get和set方法添加额外的逻辑,例如参数验证:

private int age;

public int Age
{
   get { return age; }
   set { if (value < 0) throw new ArgumentException(); age = value; } 
}

答案 6 :(得分:0)

使用自动属性,需要执行此操作。它没有任何问题,但使用自动属性,您仍然会拥有属性签名,这是非常重要的。在自动属性之前,您必须拥有属性的支持字段。只要您具有自动属性,您可以稍后将其更改为具有显式支持字段的格式,并且签名保持不变。

但是,它没有任何问题。除了公约越来越多地称为私人支持领域“_age”。

(我假设您知道为什么要拥有属性,无论是否自动,而不是公共字段。原因是对象有不同如果您将表单公共字段更改为公共属性,则签名是最安全的,因此即使没有额外的逻辑,最开始使用属性也是如此。)

答案 7 :(得分:0)

也许你想稍后改变setter或getter的行为。例如记录值是从外部更改的。对于没有属性的公共字段

,这是不可能的
   private int age;

   public int Age {

     get { return age; }
     set { 
       age = value; 
       Log("value of age changed");
     }     
   }

使用公共字段age,您必须在更改年龄值的代码中随处记录此内容。

答案 8 :(得分:0)

在这种情况下,您不会隐藏任何内容,但它可以让您以后自由地将get / set逻辑添加到您的私有字段。因此,任何使用该物业的人都不会注意到未来的差异。

答案 9 :(得分:0)

在简单的情况下什么都没有。但是,如果这两种方法中的任何一种的实现都需要额外的代码,那么就可以更容易地维护类的接口。

例如,如果您需要向setter添加更改事件。

   public int Age {

     get { return age; }
     set { 
          if ( age != value) {
              age = value; 
              OnAgeChanged();
          }
      }     
   }

您可以使用属性执行此操作,而不是破坏客户端代码。一个领域没有这个优势。

答案 10 :(得分:0)

Getters和Setter是其他类与之交互的公共接口。在复杂系统中,您通常最终会在getter和setter中进行验证和其他工作。

私人字段供内部使用。如果您需要更改类中的值但绕过所有额外的工作,您将更改私有变量。