代码之家  ›  专栏  ›  技术社区  ›  PaulB

为什么更喜欢属性而不是公共变量?[复制品]

  •  17
  • PaulB  · 技术社区  · 15 年前

    另一个能够在setter中对值进行健全性检查的是,是否存在更深层次的原因使属性优于公共变量?

    8 回复  |  直到 15 年前
        1
  •  26
  •   Konrad Rudolph    15 年前

    我们以前有过这个主题,但现在什么都找不到了。

    简而言之:你的需求可能会改变:如果现在没有健康检查,将来可能需要一个。但是,如果将公共字段更改为属性,则会破坏二进制兼容性:使用代码/库的每个客户机都必须重新编译。

    这是 坏的 因为它可能要花很多钱。

    从一开始就使用属性可以避免这个问题。这甚至对不属于库的代码也很重要。为什么?因为你永远不知道:代码(即使是高度特定于域的!)可能会证明有用,所以您希望将其重构到库中。如果您已经在使用属性来代替公共/受保护字段,那么重构过程显然变得容易得多。

    此外,在C 3.0中编写公共属性很容易,因为您只需使用自动实现的属性,就可以节省大量代码:

    public DataType MyProperty { get; set; }
    

    将为您实现必要的支持字段和getter/setter代码。

    我将添加一个个人注释:.net在这方面的行为有些懒惰。编译器可以随时将公共字段更改为属性,从而避免了这个问题。vb6已经为COM公开的类做了这项工作,我认为vb.net和c完全没有理由不这样做。也许是编译器团队中的某个人(jared?)可以对此发表评论。

        2
  •  8
  •   Sean    15 年前

    简而言之:

    • 您可以控制访问(只读,
      只写,读/写)
    • 设置时可以验证值 属性(检查是否为空等)
    • 你可以做额外的处理, 例如延迟初始化
    • 您可以更改基础 实施。例如,A 属性可以由成员支持 变量现在,但您可以更改它 由数据库行进行备份 破坏任何用户代码。
        3
  •  4
  •   Cœur N0mi    6 年前

    Jeff Atwood has blogged about it :

    有充分的理由使一个琐碎的属性,正如上面所描述的那样:

    • 反射在变量和属性上的工作方式不同,所以如果您依赖于反射,则更容易使用所有属性。
    • 不能对变量进行数据绑定。
    • 将变量更改为属性是 a breaking change .

    令人遗憾的是变量和属性之间有如此多毫无意义的摩擦;大多数时候它们做的都是完全相同的事情。 Kevin Dente 提出了一些新的语法,可以让我们在两个方面都发挥最大的作用:

    public property int Name;
    

    然而,如果变量和属性之间的区别是一个持续存在的问题,我想知道一个更激进的解决方案是否是有序的。 难道我们不能完全抛弃变量而偏爱属性吗? 属性与变量的作用不完全相同,但对可见性有更好的粒度控制吗?

        4
  •  3
  •   Mehrdad Afshari    15 年前

    将来将字段更改为属性被视为 突破变化 . 字段被视为类的实现细节,公开它们会破坏封装。

        5
  •  2
  •   Relevant Carra    10 年前

    您还可以保护写访问,并允许使用属性进行读访问:

    public int Version { get; private set; }
    
        6
  •  1
  •   LeJeune    15 年前

    如果你在一个封闭的环境中工作——你不开发一个SDK,所有的类都在同一个项目框架中使用——没有区别。

    通常的论点是,“将来可能需要对值进行一些检查,这样对属性就更容易了”。我一点也不买。

    使用公共字段更易读、装饰更少且更易于使用。

        7
  •  0
  •   Mystic    15 年前

    属性的使用使代码更加面向对象。通过将成员变量公开,您将公开您的实现。

    也看到这个 link 来自C的编程指南

        8
  •  0
  •   Pim Jager    15 年前

    对。

    考虑一个公共变量,它现在包含一个字符串,您可以简单地设置它。但是,如果您决定公共变量应该包含一个应该用字符串初始化的对象,那么您必须使用原始对象更改所有代码。但是,如果您使用了setter,那么只需更改setter,就可以使用提供的字符串初始化对象。