【问题标题】:Accessing members in your own class: use (auto)properties or not?访问您自己类中的成员:是否使用(自动)属性?
【发布时间】:2010-01-22 14:05:41
【问题描述】:

我创建了这个“问题”作为社区维基,因为没有正确或错误的答案。我只想知道社区对这个特定问题的看法。

如果您有一个带有实例变量的类,并且您还为这些实例变量创建了简单的 getter 和 setter 属性,您应该在自己的类中使用这些属性,还是应该始终使用实例变量?

在 C# 3.0 中使用自动属性使这个决定变得更加困难。

使用属性:

public class MyClass
{
    private string _name;

    // could be an auto-property of-course
    public string Name { get { return _name; } set { _name = value; } }

    public void Action()
    {
        string localVar = Name;
        // ...
        Name = "someValue";
        // ...
    }
}

使用实例变量:

public class MyClass
{
    private string _name;

    public string Name { get { return _name; } set { _name = value; } }

    public void Action()
    {
        string localVar = _name;
        // ...
        _name = "someValue";
        // ...
    }
}

(对于那些讨厌成员前缀的人,我深表歉意)

就个人而言,我总是使用后者(实例变量),因为我觉得属性应该只供其他类使用,而不是你自己。这就是为什么我也大多远离自动属性。

当然,当属性设置器(或获取器)不仅仅包装实例变量时,情况会发生变化。

是否有令人信服的理由来选择其中一个?

【问题讨论】:

    标签: c# coding-style properties design-patterns


    【解决方案1】:

    我也总是使用实例变量。原因是因为属性可能会做一些事情,比如验证参数(比如在 setter 中)是否为非空或非空。如果您在类代码中使用变量,则无需进行这些检查的额外开销(假设您知道变量值是有效的)。这些属性也可以做其他事情(例如日志记录),这对公共 API 很重要,但对内部使用不重要,所以在我看来,最好避免开销并只使用实例变量。

    【讨论】:

    • -1 大多数时候,您也需要在类内部调用这种业务逻辑。因此,基本上,您会出于充分的理由积极选择不使用该物业。例如如果你知道什么时候最好不要。否则不会有任何开销,因为在非调试场景中,无论如何都会内联简单的属性设置器/获取器。
    • @Robert Giesecke -1 发​​表评论。验证 not null 和 not empty 的参数需要额外的开销。如果没有必要这样做是没有意义的,因为这是额外的开销(请重新阅读我的原始回复)。您甚至没有考虑到属性设置器可能需要是线程安全的(即使用锁定块),在这种情况下,如果您在构造函数中并初始化变量值,您将不想调用该属性,因为例子。再说一次,您似乎没有考虑其他类型的开销。
    【解决方案2】:

    如果代码使用自己的公共接口,我认为更改内部实现会变得更加困难。

    难以解释,但请考虑以下表达方式:

    mTotalPrice = mPrice * mQuantity;
    
    mTotalPrice = Price * Quantity;
    

    如果我需要更改内部结构以用欧元而不是 $ 表示所有价格(不影响仍然使用 $ 的公共接口),在第二个表达式中该怎么做?

    一种解决方案是通过在属性中添加相反的变化来使表达式更复杂。

    mTotalPrice = Price / Rate * Quantity
    

    另一种解决方案是开始使用私有字段。

    mTotalPrice = mPrice * Quantity
    

    最终,您将获得私人和公共用途的混合。获得一致使用的唯一方法是始终使用私有字段。

    【讨论】:

      【解决方案3】:

      我也不喜欢给成员加前缀,但实际上我发现我可以偶然写出这样的东西,直到运行时才发现它。这有点诱使我避免在不需要的地方使用属性……但目前我仍然这样做!

      Public String MyString
      {
         { get { return this.MyString; } }  //<== Stack Overflow
         { set { this.myString = value; } } 
      
      }
      private String myString;
      

      【讨论】:

        【解决方案4】:

        我认为这两种方法没有区别。

        自动实现的属性只是访问以任何方式创建的私有成员的快捷方式。

        来自MSDN的示例:

        class Customer
        {
            // Auto-Impl Properties for trivial get and set
            public double TotalPurchases { get; set; }
            public string Name { get; set; }
            public int CustomerID { get; set; }
        
            // Constructor
            public Customer(double purchases, string name, int ID)
            {
                TotalPurchases = purchases;
                Name = name;
                CustomerID = ID;
            }
            // Methods
            public string GetContactInfo() {return "ContactInfo";}
            public string GetTransactionHistory() {return "History";}
        
            // .. Additional methods, events, etc.
        }
        

        【讨论】:

          【解决方案5】:

          99% 的时间我使用属性而不是实例变量。过去,我处理过很多使用实例变量的代码,当有与该变量相关的错误时,我必须在引用它的每一行代码上放置一个断点。

          我决定改用属性,无论是公共的还是私有的,来包裹实例变量。这样做意味着,如果我需要调试实例变量的问题,我只需在属性的 getter/setter 中放置一个断点,而不是(可能)在代码中散布很多断点。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-03-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-03-15
            • 1970-01-01
            相关资源
            最近更新 更多