【问题标题】:Is using get set properties of C# considered good practice?使用 C# 的 get set 属性是否被认为是好的做法?
【发布时间】:2010-12-22 06:17:48
【问题描述】:

我的问题很简单,使用 C# 的 get set 属性是否被认为是好的,甚至比编写 getter 和 setter 方法更好?当您使用这些属性时,您不必将您的类数据成员声明为 public 吗?我问这个是因为我的教授说数据成员应该永远被宣布为公开的,因为这被认为是不好的做法。

这个....

class GetSetExample
{
    public int someInt { get; set; }
}

vs 这...

class NonGetSetExample
{
    private int someInt;
}

编辑:

谢谢大家!你所有的答案都帮助了我,我适当地对你的答案投了赞成票。

【问题讨论】:

  • 这实际上是我们在面试新申请时会问的问题。你为什么要使用第一个而不是第二个:-)
  • 教授应该足够聪明,知道不要使用绝对!除非他将“从不”重新定义为“不理解并接受可能的后果”……

标签: c# .net


【解决方案1】:

这个:

class GetSetExample
{
    public int someInt { get; set; }
}

真的和这个一样:

class GetSetExample
{
    private int _someInt;
    public int someInt {
        get { return _someInt; }
        set { _someInt = value; }
    }
}

get; set; 语法只是一个方便的简写,当 getter 和 setter 不做任何特殊操作时可以使用它。

因此,您不是公开一个公共成员,而是定义一个私有成员并提供获取/设置方法来访问它。

【讨论】:

    【解决方案2】:

    是的,出于多种原因,成员通常不应该在良好的设计中被宣布为公共。想想你以后继承类的OOP。有点难以覆盖一个字段。 :-) 它还可以防止您直接访问您的内部结构。

    简单的get;放;设计是在 C# 2.0 中引入的。它基本上与使用支持它的私有成员声明所有内容相同(在反射器之类的工具中将其反编译并查看)。

    public int someInt{get;set;} 
    

    直接等于

    private int m_someInt;
    public int someInt{
      get { return m_someInt; }
      set { m_someInt = value; }
    } 
    

    使用简化的 getter/setter 的好处在于,当您以后想用更多的胆量来填充实现时,不会破坏 ABI 兼容性。

    不用担心 getter/setter 会通过间接方式减慢您的代码速度。 JIT 有一个叫做内联的东西,它使得使用 getter/setter 和直接访问字段一样有效。

    【讨论】:

    • 我同意。考虑一个长寿的 .NET 库。要维护它,在将某些东西暴露给外界之前必须非常小心,并且大多数时候您应该暴露一个属性,而不是一个字段。这是在未来版本中最安全的方式,您可以随意更改此属性的实现,而不会损害调用程序集。如果直接暴露一个字段会发生什么?那一定是一场无尽的噩梦,因为从那时起你永远无法改变它。
    【解决方案3】:

    是的。数据成员应该是私有的,并且自动属性允许它并以正确的方式提供公共访问。

    但是你应该小心。了解上下文非常重要。在线程应用程序中,在另一个相关属性之后更新一个属性可能会损害一致性。在这种情况下,以适当的方式更新两个私有数据成员的 setter 方法更有意义。

    【讨论】:

      【解决方案4】:

      在您的第一个示例中,C# 自动生成私有支持字段,因此从技术上讲,数据成员不会仅声明为公共的 getter/setter。

      【讨论】:

      • 技术上,但这是一个毫无意义的区别。
      • 并非如此。属性可以用于其他领域,而方法或字段则不能。想到了自动绑定。
      • 在某些情况下实际上是相当重要的。如果您声明一个公共变量,那么除非您想将 ABI 更改为该程序集,否则您将被困在公共变量中。用 { 得到;放; } 公共属性,所有公共访问都是通过访问器方法发生的,因此您可以稍后更改访问器方法以具有不同的功能,而无需强制每个人重新编译引用您的程序集的应用程序。
      • 是的......你们两个写了准确的回复,但他们没有解决我的评论。他强调数据成员不是公开的;我的评论是:那又怎样?
      • 柔滑的,迈克尔正确地回答了你的“那又怎样”。有关更多详细信息,CLR 在后台以不同方式编译它们,这会影响您执行基于反射的操作的方式(例如他的数据绑定示例)。
      【解决方案5】:

      因为使用公共数据成员,该数据成员可以更改或可以从类中读取 并且您无法控制读/写操作的可访问性,但您可以控制属性 例如读/写流考虑这个语句:

       public MyVar{private get; public set;}
      

      表示MyVar 的值只能在类内部更改,并且可以在类外读取(私下读取和公开读取),而仅使用公共数据成员是不可能的

      【讨论】:

      • 一个新的用户提示:当这个问题已经有很多答案时,添加一个非常老的问题的答案并不是很有用。
      【解决方案6】:

      在“纯粹的”面向对象的方法中,完全不能公开对象的状态,这适用于属性,因为它们是在 .NET 和 Java/EJB 的 get_set_properteis 中实现的。这个想法是,通过公开对象的状态,您正在为对象的内部数据表示创建外部依赖项。纯对象设计将所有交互减少到带有参数的消息。

      回到现实世界:如果你试图在工作中实施如此严格的理论方法,你要么会被笑出办公室,要么会被打得一塌糊涂。属性非常受欢迎,因为它们是纯对象设计和完全公开的私有数据之间的合理折衷。

      【讨论】:

        【解决方案7】:

        这很合理,您的教授(没有上下文)是错误的。但是无论如何,使用“自动属性”就可以了,无论它们是公共的还是私有的,您都可以这样做。

        虽然根据我的经验,每当我使用它时,我几乎不可避免地最终需要在其中编写一些逻辑,因此无法使用自动道具。

        【讨论】:

        • 我猜上下文应该是 Java(或者可能是 C++),因为 Java 没有 C# 的属性。
        • 如果您可以完全控制整个源代码并且它总是一起编译,那么无论您使用属性还是公共变量(特殊情况除外)都没有什么区别。但是,在不同的人编写代码的不同部分的情况下,它变得更加重要。专业库不会将公共变量暴露给外部代码。
        • 看了这些回复,感觉自己有点像在暮光之城。
        • @FrustratedWithFormsDesigner:Java 中的惯用构造是定义方法getMyFieldsetMyField 来获取和设置私有支持字段myField
        【解决方案8】:

        你的教授说的很对。

        考虑一下为什么应该避免使用“getter”的这个简单示例:在您的程序中可能有 1,000 次对 getX() 方法的调用,并且每一次调用都假定返回值是一种特定类型。例如,getX() 的返回值可能存储在局部变量中,并且变量类型必须与返回值类型匹配。如果您需要更改对象的实现方式以使 X 的类型发生更改,那么您将陷入困境。如果 X 曾经是 int,但现在必须是 long,那么您现在将得到 1,000 个编译错误。如果您通过将返回值强制转换为int 来错误地解决了问题,则代码将编译干净但无法正常工作。 (返回值可能会被截断。)您必须修改围绕这 1,000 个调用中的每一个调用的代码以补偿更改。至少,我不想做那么多工作。

        Holub On Patterns

        【讨论】:

        • 这在问题的上下文中没有任何意义。有什么选择?永远不要让别人找回班级成员?
        • Sterno:好吧,甚至他的教授似乎也是这么说的(“我的教授说数据成员永远不应该被宣布为公开的”)。为什么将数据成员声明为 public 不好,但是写更多的代码来完全相同的效果是可以的?
        • 我同意他教授的说法。我只是认为您引用的内容在实际应用中没有多大意义。 Resharper 之类的工具使更改变量类型变得非常简单,即使您没有使用 getter/setter。方法,这并不意味着您将避免与更改属性类型相关的痛苦。因此,虽然我支持他的教授所说的话,但我认为这句话并不能很好地支持这一论点。
        • 但是为什么公共数据成员完全不好呢?什么支持这个论点?
        • 我的想法与上面 Zac Bowling 的回答非常吻合。
        猜你喜欢
        • 1970-01-01
        • 2011-04-10
        • 2018-08-11
        • 1970-01-01
        • 2019-06-08
        • 1970-01-01
        • 2015-10-29
        • 2013-04-12
        • 1970-01-01
        相关资源
        最近更新 更多