何时应该使用字段而不是属性?

11

有人能清晰地阐述在类设计中何时使用字段(field),何时使用属性(property)吗?

考虑以下情况:

public string Name;

或:

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

我意识到第二种方法更加恰当和灵活,所以我通常会使用它。

但是为什么我看到有人使用第一种方法呢?他们是懒得改还是在某些特定情况下,第一种方法是正确的选择?这只是个人偏好吗?


顺便提一下,使用下划线作为私有成员的命名方式并不是.NET的惯用方式。请查看http://msdn.microsoft.com/en-us/library/ms229045.aspx。 - Alan
看看这个无聊的东西。 - Alan
实际上,我发现在字段前加_(尽管使用驼峰命名法)非常有用,因为它明确地将字段与局部变量和参数区分开来。 - Peter Lillevold
@Alan,设计指南只是指南。至少对于内部和私人事务,应该根据团队的需要进行。但对于公共事务,我同意我们应该遵循一个标准。 - Peter Lillevold
显示剩余5条评论
7个回答

15

在C# 3.0中,你其实可以这样写:

public string Name {get; set;}

使用属性可以实现良好的封装性,可以选择允许设置值、获取值或两者同时。而使用公共成员变量则无法做到这一点。因此通常建议在类设计中使用属性来进行get/set操作,尤其是在C# 3.0中可以使用更加简洁的语法来定义属性。

对于何时使用属性和何时使用成员变量,建议永远不要使用公共成员变量,而是始终使用属性,因为属性更加安全和灵活。当然,人们可能会有懒惰心理并直接使用公共成员变量,但是在C# 3.0中你可以使用更加简洁的语法来定义属性,只需输入prop然后点击<tab>即可快速添加属性。


4
注意:在编写代码时,不应该使用“shouldn't ever”这样的措辞。 - Alan
1
“你不应该使用公共属性”听起来更像是个人意见而不是技术答案。 - user3325915

14

关于Alan的回答,这里提供一些额外的信息:

public string Name {get; set;}

是相同的。
private string _Name;

public string Name{   
get { return _Name; }   
set { _Name = value; }
}

如果您想禁止对 Name 属性进行设置操作,可以使用以下代码:

public string Name {get; private set;}


4

属性比字段更易于维护,您可以在setter/getter中封装逻辑,从而隐藏实现。

它们还使重构更容易。

更多信息:


1
除了已经提到的更喜欢属性的原因之外,System.ComponentModel 中还有很多与数据绑定和更改通知相关的酷炫功能,这些功能只适用于属性而不是字段。例如,请查看 PropertyChangedHandler 周围的文档。

是的!通过使用字段可以破坏绑定和序列化。 - Ian W

0

使用属性可以控制其安全性:

public string Foo { protected get; private set; }

属性提供了一种简单的方式来触发事件:

public string Foo
{
  get { return _foo; }
}
set
{
  bool cancel = false;
  if(BeforeEvent != null) // EventHandler<CancelEventArgs> BeforeEvent
  {
    CancelEventArgs e = new CancelEventArgs();
    BeforeEvent(this, e);
    cancel = e.Cancel;
  }
  if(!cancel)
  {
    _foo = value;
    if(AfterEvent != null) // EventHandler<EventArgs> AfterEvent
    {
      AfterEvent(this, new EventArgs());
    }
  }
}

我经常使用这样的代码:

string Foo
{
  set
  {
    IsFooSet = value != null;
  }
}

bool IsFooSet
{
  get { return _isFoo; }
  set
  { 
   _isFoo = value;
   if(value) // some event raise or controls on form change
  }
}

0

像上面定义的属性就像是一个getter和setter。使用属性的唯一好处是你可以像使用带有访问限制的变量一样对待它。

public string Name { get; private set; }

这个属性可以公开访问,但只能私下设置。(你肯定不希望有人在没有你同意的情况下更改你的名字吧!;))


0
当您将字段设置为公共时,您允许用户对该字段进行任何操作。他们可以分配意外的值、无效的值、可能导致溢出的值等。
使用属性,您可以控制是否允许设置新值到字段中,在存储之前对值进行处理,通知有关方面有关字段值的更改等。同样的想法也适用于通过getter返回值。对于.NET框架2.0及以上版本,您可以为getter、setter设置访问器。例如,如果您只希望用户对该字段具有读取访问权限,则可以将getter设置为public,而将setter设置为private或protected。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接