看到发生这种情况的一些代码示例:
public class Foo
{
string[] m_workID;
public string[] WorkID
{
get
{
return m_workID;
}
private set
{
m_workID = value;
}
}
}
这有什么意义? 由于使用m_workID不必要。
答案 0 :(得分:32)
通常,重点是将实现(字段)与 API (属性)分开。
稍后您可以,如果您愿意,可以在属性中放置逻辑,记录等,而不会破坏源或二进制兼容性 - 但更重要的是,您要说的是您的类型愿意做什么,而不是它将如何做它
我an article提供了使用属性而非公共字段的更多好处。
在C#3中,您可以使用自动实现的属性使所有这些变得更加简单:
public class Foo
{
public string[] WorkID { get; private set; }
}
此时你仍然有一个公共getter和一个私有的setter,但是在幕后为你生成了支持字段(和属性实现)。在任何时候,您都可以将其更改为具有支持字段的“正常”完全实现的属性,并且您仍将具有二进制和源兼容性。 (请注意,序列化对象的兼容性是另一回事。)
此外,在这种情况下,你不能镜像你想要的行为(公开读取值但是私下写它)的字段 - 你可以有一个只读字段,但是你只能 在构造函数中写入它。就个人而言,我希望有一个类似的简写:
public class Foo
{
private readonly int id;
public int Id { get { return id; } }
...
}
因为我喜欢不可变类型,但这是另一回事。
在另一个不同的问题中,无论如何暴露这样的数组通常不是一个好主意 - 即使调用者无法更改WorkID
引用的数组,他们也可以更改数组的内容,这可能不是你想要的。
在你给出的可以没有属性设置器的示例中,只是直接在同一个类中设置字段,但这意味着如果你想添加日志等你必须找到所有这些写作。
答案 1 :(得分:8)
属性本身不提供 put 数据的任何地方 - 您需要字段(m_workID
)进行存储,但它完全正确到由于很多原因,隐藏在财产背后。在C#3.0中,您可以将其减少为:
public string[] WorkID {get; private set;}
这将做很多相同的事情。请注意,暴露数组本身可能会有问题,因为没有保护数组中数据的机制 - 至少使用IList<string>
您可以(如果需要)添加额外的代码以进行健全性检查事情,或者可以使它永不变化。我不是说这需要修复,但需要注意。
答案 2 :(得分:2)
除了Object Oriented philosophy of data encapsulation之外,每当您的财产被读/写时您需要做某事时,它会有所帮助。 您可以在开发中稍后执行日志,验证或任何其他方法调用。
如果您的媒体资源是公开的,则必须查看所有代码以查找和修改您的代码。如果您的代码被其他人用作库,该怎么办?
如果您的属性是私有的,具有适当的get / set方法,那么您可以更改get / set,这就是全部。
答案 3 :(得分:2)
您可以使用C#3.0自动属性功能来节省输入时间:
public class Foo
{
public string[] WorkID
{
get; private set;
}
}
此外,与字段相比,属性提供了许多优势:
属性可以是虚拟的
属性隐藏实现细节(并非所有属性都只是简单的变量访问器)
属性可以包含验证和日志记录代码并引发更改事件
接口不能包含字段,但属性
答案 4 :(得分:0)
很多时候,您只想提供对字段的读取权限。通过使用属性,您可以提供此访问权限。如您所述,您可能希望在访问字段之前执行操作(例如,延迟加载)。你有很多代码,除非你还在.Net 2.0中工作,否则就没有必要了。