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

时间:2010-01-25 13:00:10

标签: c#

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

public class Foo
{
    string[] m_workID;
    public string[] WorkID
    {
        get
        {
            return m_workID;
        }
        private set
        {
            m_workID = value;
        }
    }
}

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

5 个答案:

答案 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中工作,否则就没有必要了。