157

注意:这是在我开始使用 C# 时发布的。凭借 2014 年的知识,我可以真正地说自动属性是 C# 语言发生过的最好的事情之一。

我习惯于使用私有和公共字段在 C# 中创建我的属性:

private string title;
public string Title
{
    get { return title;  }
    set { title = value;  }
}

现在,使用.NET 3.0,我们获得了自动属性:

public string Title { get; set; }

我知道这更像是一个哲学/主观问题,但是除了为每个字段保存五行代码之外,还有什么理由使用这些自动属性?我个人的抱怨是这些属性对我隐藏了一些东西,而且我不是黑魔法的忠实粉丝。

事实上,隐藏的私有字段甚至没有出现在调试器中,考虑到 get/set 函数什么都不做,这是可以的。但是当我想实际实现一些 getter/setter 逻辑时,无论如何我都必须使用 private/public 对。

我看到了节省大量代码(一行对六行)而不会失去稍后更改 getter/setter 逻辑的能力的好处,但是我已经可以通过简单地声明一个公共字段“公共字符串标题”来做到这一点,而无需{ 获取的需要;放; } 块,因此甚至可以节省更多代码。

那么,我在这里缺少什么?为什么有人真的想使用自动属性?

4

18 回答 18

121

我们一直在 Stack Overflow 中使用它们。

您可能还对属性与公共变量的讨论感兴趣。恕我直言,这确实是对它的反应,为此,它很棒。

于 2008-08-12T23:13:41.470 回答
64

是的,它只是保存代码。当您拥有大量它们时,阅读起来会更容易。它们编写起来更快,更容易维护。保存代码始终是一个好目标。

您可以设置不同的范围:

public string PropertyName { get; private set; }

这样属性只能在类内部更改。这并不是真正不可变的,因为您仍然可以通过反射访问私有设置器。

从 C#6 开始,您还可以创建真正的readonly属性 - 即不能在构造函数之外更改的不可变属性:

public string PropertyName { get; }

public MyClass() { this.PropertyName = "whatever"; }

在编译时将变为:

readonly string pName;
public string PropertyName { get { return this.pName; } }

public MyClass() { this.pName = "whatever"; }

在具有大量成员的不可变类中,这可以节省大量多余的代码。

于 2008-08-13T07:09:06.127 回答
46

使用字段而不是属性的三大缺点是:

  1. 您不能对字段进行数据绑定,而可以对属性进行数据绑定
  2. 如果您开始使用字段,则以后不能(轻松)将它们更改为属性
  3. 有一些属性可以添加到属性中,但不能添加到字段中
于 2008-08-12T23:13:33.543 回答
30

来自 C++ 的创造者 Bjarne Stroustrup:

我特别不喜欢有很多 get 和 set 函数的类。这通常表明它最初不应该是一个类。它只是一个数据结构。如果它真的是一个数据结构,那就让它成为一个数据结构。

你知道吗?他是对的。您多久只是将私有字段包装在 get 和 set 中,而实际上在 get/set 中没有做任何事情,仅仅是因为它是“面向对象”的事情。这是微软对问题的解决方案;它们基本上是您可以绑定的公共字段。

于 2008-10-08T11:21:40.680 回答
29

我个人喜欢汽车属性。保存代码行有什么问题?如果您想在 getter 或 setter 中做一些事情,那么稍后将它们转换为普通属性是没有问题的。

正如您所说,您可以使用字段,如果您想稍后向它们添加逻辑,您可以将它们转换为属性。但这可能会出现任何使用反射的问题(可能还有其他地方?)。

此外,这些属性允许您为 getter 和 setter 设置不同的访问级别,这是您无法对字段执行的操作。

我想它与 var 关键字相同。个人喜好问题。

于 2008-08-12T23:13:15.790 回答
18

似乎没有人提到的一件事是,不幸的是自动属性对不可变对象(通常是不可变结构)没有用处。因为为此你真的应该这样做:

private readonly string title;
public string Title
{
    get { return this.title; }
}

(该字段在构造函数中通过传递的参数进行初始化,然后是只读的。)

get所以这比简单的/自动属性有优势private set

于 2008-08-27T18:04:14.293 回答
12

我总是创建属性而不是公共字段,因为您可以在接口定义中使用属性,但不能在接口定义中使用公共字段。

于 2008-12-05T10:59:42.123 回答
8

与 C# 中的其他任何东西一样,自动属性都是一种黑魔法。一旦您从编译到 IL 的角度考虑它,而不是首先将其扩展为普通的 C# 属性,它就比许多其他语言结构少了很多黑魔法。

于 2008-08-18T00:27:08.307 回答
5

我一直使用自动属性。在 C#3 之前,我不会为所有的输入而烦恼,而是使用公共变量。

我唯一想念的是能够做到这一点:

public string Name = "DefaultName";

您必须将默认值转移到具有属性的构造函数中。乏味:-(

于 2008-08-12T23:22:07.147 回答
5

我认为任何直观且减少代码行数的结构都是一大优势。

正是这些特性使得像 Ruby 这样的语言如此强大(动态特性也有助于减少多余的代码)。

Ruby 一直以来都是这样的:

attr_accessor :my_property
attr_reader :my_getter
attr_writer :my_setter
于 2008-08-13T00:14:48.897 回答
2

我对他们的唯一问题是他们走得不够远。同一版本的编译器添加了自动属性,添加了部分方法。为什么他们没有把两者放在一起是超出我的。一个简单的“部分 On<PropertyName>Changed”会让这些东西非常有用。

于 2008-08-13T01:36:03.617 回答
2

它很简单,很短,如果你想在属性的主体内创建一个真正的实现,它不会破坏你的类型的外部接口。

就如此容易。

于 2008-09-07T08:06:44.653 回答
1

这里需要注意的一点是,据我了解,这只是C# 3.0 端的语法糖,这意味着编译器生成的 IL 是相同的。我同意避免使用黑魔法,但同样的,同一件事的行数越少通常是一件好事。

于 2008-08-17T22:40:15.170 回答
1

在我看来,您应该始终使用自动属性而不是公共字段。也就是说,这是一个折衷方案:

从使用属性命名约定的内部字段开始。当你第一次

  • 需要从其程序集外部访问该字段,或
  • 需要将逻辑附加到 getter/setter

做这个:

  1. 重命名字段
  2. 将其设为私有
  3. 添加公共属性

您的客户端代码不需要更改。

不过,总有一天,您的系统会发展壮大,您会将其分解为单独的程序集和多个解决方案。发生这种情况时,任何暴露的字段都会回来困扰您,因为正如 Jeff 所提到的,将公共字段更改为公共属性是一个破坏性的 API 更改

于 2008-08-17T23:19:30.987 回答
0

我使用 CodeRush,它比自动属性更快。

去做这个:

 private string title;
public string Title
{
    get { return title;  }
    set { title = value;  }
}

总共需要八次击键。

于 2008-08-21T11:13:54.627 回答
0

好吧,使用代码片段,同名的自动属性总共将是七次击键;)

于 2008-08-26T09:01:06.933 回答
0

@Domenic:我不明白..你不能用自动属性做到这一点吗?:

public string Title { get; }

或者

public string Title { get; private set; }

这是你指的吗?

于 2008-08-30T11:59:37.067 回答
0

我对自动属性最大的抱怨是它们旨在节省时间,但我经常发现我必须稍后将它们扩展为完整的属性。

VS2008 缺少的是Explode Auto-Property重构。

我们有一个封装字段重构的事实使我的工作方式更快,只使用公共字段。

于 2008-12-05T10:24:51.333 回答