关于C#:属性与公共成员变量

Properties vs Public member variables

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
What is the difference between a field and a property in C#

我是一个初学者,我已经阅读了所有关于类属性的内容。Books声明属性允许您间接访问成员变量。好吧,那么它与公开和直接访问字段有什么不同呢?

以下是Jesse Liberty学习C 3.0的引言:

For example, you might want external
classes to be able to read a value, but not change it; or you might want to write
some code so that the internal field can accept only values in a certain range. If you
grant external classes free access to your member fields, you can’t control any of that.

我不明白他在说什么。有人能进一步解释这一点吗,或者举例说明我为什么要使用某个属性而不公开该字段。正如我现在所理解的,他们都会完成同样的事情……所以我显然错过了一些东西。


到目前为止提供的其他答案提供了访问器/转换器逻辑优势的详细信息,但似乎都遗漏了关于对象封装的思想要点。

你看,类成员字段是一个实现细节。例如,如果有一个表示集合的类,那么可以将其实现为链接列表(并通过公共字段公开根节点),或者将其实现为可调整大小的数组并公开index0成员。

揭示实现细节的问题是,您会丢失类与其使用者之间任何类型的定义接口。通过确保所有操作都是通过定义的方法(由类本身控制)完成的,您可以更容易地使用和提供长期的观点。例如,您可以更容易地将集合实现从一种类型(链接列表)转换为另一种类型(数组),而不会破坏与类的消费者的任何契约。

不要担心琐碎的访问器/转换器方法对性能的影响:JIT编译器将内联属性方法。如果运行一些基准测试,您将看到属性与字段的性能是相同的。


他说属性可以提供getter,但不能提供setter,因此使它们成为只读的(例如)

属性只是一种方法的句法糖,例如

1
public int SomeProperty { get; set; }

只是糖

1
2
3
4
5
6
7
8
9
10
11
private int _someProperty;

public int SomeProperty_get()
{
   return _someProperty;
}

public void SomeProperty_set(int value)
{
   _someProperty = value;
}

这意味着属性设置器/getter可以应用仅公共字段不能应用的逻辑

编辑:我不确定clr为自动属性提供了哪些字段名-这只是一个例子:)

编辑2:

只读属性的示例:

1
public int SomeProperty { get; }

最后是一个公共的读-私有的写(用于自动属性)

1
public int SomeProperty { get; private set; }

当您不必费心在中键入支持字段时非常有用:)

请记住,如果您希望将逻辑应用于成员,那么属性就是可行的方法。这是许多框架的工作方式(例如,通过使用属性来跟踪"脏"对象,以告诉某种对象管理器某些内容已更改,使用公共字段是不可能的)


属性可能有副作用,它们围绕"getter"和"setter"方法提供了语法上的优势。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyClass {

   int sizeValue = 0;

   public int Size {
      get {
         return sizeValue;
      }
      set {
         if ( value < 10 ) throw new Exception("Size too small");
         sizeValue = value;
      }
   }
}

属性也可以对get和set具有不同的保护级别,不能对字段进行保护。

1
2
3
4
5
6
7
8
9
10
11
12
public class MyOtherClass {

   // only this object can set this.
   public int Level {
      get; private set;
   }

   // only things in the same assembly can set this.
   public string Name {
      get; internal set;
   }
}


"属性"和"成员访问"之间有许多重要的区别。

最重要的是,您可以通过属性使成员成为只读的(您可以访问状态,但不能更改它)。就像Java中的"GETTER()"和"SETTER()"方法一样。

还可以从属性返回计算值(生成一个"即时"的值,就像它是一个变量一样)。


属性可以配置为:

它们是只读的,Public MyProp {get;}

它们只写Public MyProp {set;}

它们可以被外部对象读取,但只能由类的内部设置

公营企业

正如其他人发布的那样,您也可以将逻辑放入getter和setter中。例如,在允许属性下注设置为新值之前,可以检查该值是否可接受。

对于公共字段,您不能这样做。

基本上,公共领域是你能拥有的最愚蠢的财产。鉴于.NET现在允许为您的属性自动打包字段。再也没有充分的理由使用公共领域了。


如果你有EDOCX1[0]我可以把它设为-200或20000,你对此无能为力。

例如,如果使用属性,可以检查年龄是否在0到150之间。

编辑:根据伊恩诺顿的例子(伙计,那太快了)