【问题标题】:Should properties or fields be used internally in classes?属性或字段是否应该在类内部使用?
【发布时间】:2018-07-14 17:21:02
【问题描述】:

通常,您希望通过为内部状态提供 getter 和 setter 来封装数据。示例:

public class Person {
    private int age;
    public int Age { 
        get { return age; }
        set { age = value; }
    }
}

void Main() {
    Person alice = new Person();
    alice.Age = 20;
}

但是假设我们发生了这种情况:

public class Person {
    private int age;
    public int Age { 
        get { return age; }
        set { age = value; }
    }

    public String WhatIsMyAge() {
        return "My age is: " + ???;
    }
}

void Main() {
    Person alice = new Person();
    alice.Age = 20;

    Console.WriteLine(alice.WhatIsMyAge());
}

在这里使用属性或字段更好吗?有关系吗?既然我们在原生类里面,我们还关心封装内部吗?

【问题讨论】:

  • Age 对于字段来说是一个糟糕的选择,因为它是可变的。 Birthdate 是更好的选择。
  • 除非有非常明确的理由使用字段,否则我总是使用属性。如果您需要更改某些内容(例如,如果您想根据出生日期计算年龄),您将需要寻找一个点
  • @DourHighArch 我想我明白你的意思是它是可变的一个糟糕的选择,但这仅仅是因为有人可能会不小心改变它,还是它是一个更编程的问题? (例如线程安全)
  • 您只需使用该属性。否则,你为什么要一个?
  • 可变字段存在很多问题,包括持久性、相等比较、竞争条件;但是您的示例的最大问题是正确性。如果检测到Age == 20,则无法知道它是否正确;自设置以来,它可能已更改。是的,有时可变字段是必要的,但情况并非如此;生日是不可变的,您可以从中计算年龄。

标签: c# oop properties field encapsulation


【解决方案1】:

始终使用该属性,尤其是在类代码中。我什至会说:在类代码中意外使用属性的支持字段严重错误。

应努力避免意外使用支持字段:

  • 如果您使用自动实现属性,则没有您可能意外使用的支持字段名称。 (当然有一个,但它没有名字;所以不小心使用它是不可能的)。
  • 如果自动实现属性不够(不再)足够,我总是在支持字段中附加一个下划线。 age 和 Age 更容易混淆 _Age 和 Age。
  • 有些人超越了这一点。就像使用 Dictionary<string, object> 作为每个类的支持字段一样。使用“CallerMemberName”和类似的语法糖,找出用作索引的属性名称可能很简单。

【讨论】:

  • 为什么这是一个严重的错误?
  • 拥有属性(而不是原始字段)的很大一部分原因是您(可能)在获取和设置它们时调用的代码。但是一旦你有其他代码(如构造函数)忽略属性并使用支持字段,你永远不能在不破坏预期行为的代码的情况下收回它。
【解决方案2】:

在你的例子中:

private int age;
public int Age { 
    get { return age; }
    set { age = value; }
}

您应该使用auto-implemented properties anyway

但是,如果您有一个支持字段来在属性的 getter 或 setter 中提供额外的逻辑,例如验证,请务必使用属性而不是支持字段:这使得类型无法将值分配给属性通过属性的 setter 分配时不会通过验证。

读取支持字段应该是安全的,因为getters shouldn't contain logic anyway。但为了保持一致性,请通过属性执行读取和写入操作。

【讨论】:

    【解决方案3】:

    如果您使用没有任何额外功能的简单属性,那没关系。 但是,在这种情况下,你为什么不选择使用Auto-implemented properties 呢?

    如果您的属性 getter 或 setter 包含额外的功能,那么无论您是使用属性访问器还是直接使用支持字段都无关紧要。这一切都取决于所需的行为。

    【讨论】:

    • 我愿意。但是我明确地添加了支持变量来帮助我的问题。
    猜你喜欢
    • 2019-01-19
    • 1970-01-01
    • 1970-01-01
    • 2013-03-12
    • 2010-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多