为什么使用私有成员然后使用公共属性来设置它们?

Rub*_*ans 20 c#

看到发生这种情况的一些代码示例:

public class Foo
{
    string[] m_workID;
    public string[] WorkID
    {
        get
        {
            return m_workID;
        }
        private set
        {
            m_workID = value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这有什么意义?由于使用m_workID不必要.

Jon*_*eet 32

通常,重点是将实现(字段)与API(属性)分开.

如果您愿意,您可以在不破坏源或二进制兼容性的情况下将逻辑,日志记录等放入属性中 - 但更重要的是,您要说的是您的类型愿意做什么,而不是它将如何做.

我有一篇文章给出了使用属性而不是公共字段的更多好处.

在C#3中,您可以使用自动实现的属性使所有这些变得更加简单:

public class Foo
{
    public string[] WorkID { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

此时,您仍然拥有公共getter和私有setter,但在后台为您生成了支持字段(和属性实现).在任何时候,您都可以将其更改为具有支持字段的"正常"完全实现的属性,并且您仍将具有二进制和源兼容性.(序列化对象的兼容性是另一回事,请注意.)

此外,在这种情况下,您无法镜像您想要的行为(公开读取值但私下写入它)与字段 - 您可以有一个只读字段,但是您只能在构造函数中写入它.就个人而言,我希望有一个类似的简写:

public class Foo
{
    private readonly int id;
    public int Id { get { return id; } }

    ...
}
Run Code Online (Sandbox Code Playgroud)

因为我喜欢不可变类型,但这是另一回事.

另一个不同的问题上,无论如何都暴露这样的数组通常不是一个好主意 - 即使调用者无法更改哪个数组WorkID引用,他们也可以更改数组的内容,这可能不是你想要的.

在您给出的示例中,您可以在没有属性设置器的情况下离开,只需将字段直接设置在同一个类中,但这意味着如果您想要添加日志记录等,则必须找到所有这些写入.


Mar*_*ell 8

一个属性本身并不提供放置数据的任何地方- 你需要字段(m_workID)来存储,但由于很多很多原因它隐藏在属性后面是完全正确的.在C#3.0中,您可以将其减少为:

 public string[] WorkID {get; private set;}
Run Code Online (Sandbox Code Playgroud)

哪个会做很多相同的事情.请注意,暴露数组本身可能会有问题,因为没有用于保护数组中数据的机制 - 至少IList<string>可以(如果需要)可以添加额外的代码来进行健全性检查,或者可以使其不可变.我不是说这需要修复,但需要注意.