Share via


CA1024:在适用处使用属性

类型名

UsePropertiesWhereAppropriate

CheckId

CA1024

类别

Microsoft.Design

是否重大更改

原因

公共或受保护方法的名称以 Get 开头,没有采用任何参数或返回的值不是数组。

规则说明

在大多数情况下,属性代表数据,而方法执行操作。 访问属性的方式与访问字段的方式相似,因此使用它们更容易。 如果存在下列条件之一,方法就很适于成为属性:

  • 不采用任何参数并返回对象的状态信息。

  • 接受单个参数来设置对象的部分状态。

属性的表现应当与字段一样;如果该方法不是这样,则不应将其更改为属性。 在下列情况下,方法比属性更好:

  • 方法执行耗时的操作。 与设置或获取字段值所需的时间相比,此方法的速度明显较慢。

  • 方法执行转换。 访问字段不会返回它所存储的数据的转换版本。

  • Get 方法会产生明显副作用。 检索字段的值不会产生任何副作用。

  • 执行的顺序很重要。 设置字段的值并不依赖于其他操作的发生。

  • 连续调用两次方法会产生不同的结果。

  • 方法是静态的,但返回了调用方可更改的对象。 调用方不能通过检索某字段的值来更改该字段存储的数据。

  • 方法返回数组。

如何解决冲突

要修复与该规则的冲突,请将方法更改为属性。

何时禁止显示警告

如果方法至少满足上文中列出的一个条件,则禁止显示与该规则有关的警告。

在调试器中控制属性扩展

程序员避免使用属性的一个原因,是他们不希望调试器自动展开属性。 例如,属性可能涉及分配一个大型对象或调用 P/Invoke,但它实际上可能不具有任何明显的副作用。

通过应用 System.Diagnostics.DebuggerBrowsableAttribute 可以阻止调试器自动展开属性。 下面的示例演示如何将此特性应用到实例属性。

Imports System 
Imports System.Diagnostics 

Namespace Microsoft.Samples 

    Public Class TestClass 

        ' [...] 

        <DebuggerBrowsable(DebuggerBrowsableState.Never)> _ 
        Public ReadOnly Property LargeObject() As LargeObject 
            Get 
                ' Allocate large object 
                ' [...] 
            End Get 
        End Property 

    End Class 

End Namespace
using System; 
using System.Diagnostics; 

namespace Microsoft.Samples 
{ 
    public class TestClass 
    { 
        // [...] 

        [DebuggerBrowsable(DebuggerBrowsableState.Never)] 
        public LargeObject LargeObject 
        { 
            get 
            { 
                // Allocate large object 
                // [...] 

        }
    }
}

示例

下面的示例包含多个应转换为属性的方法,还包含多个由于表现与字段不同而不应转换的方法。

using System;
using System.Globalization;
using System.Collections;
namespace DesignLibrary
{
   // Illustrates the behavior of rule: 
   //  UsePropertiesWhereAppropriate.

   public class Appointment
   {
      static long nextAppointmentID;
      static double[] discountScale = {5.0, 10.0, 33.0};
      string customerName;
      long customerID;
      DateTime when;

      // Static constructor.
      static Appointment()
      {
         // Initializes the static variable for Next appointment ID.
      }

      // This method will violate the rule, but should not be a property.
      // This method has an observable side effect. 
      // Calling the method twice in succession creates different results.
      public static long GetNextAvailableID()
      {
         nextAppointmentID++;
         return nextAppointmentID - 1;
      }

      // This method will violate the rule, but should not be a property.
      // This method performs a time-consuming operation. 
      // This method returns an array.

      public Appointment[] GetCustomerHistory()
      {
         // Connect to a database to get the customer's appointment history.
         return LoadHistoryFromDB(customerID);
      }

      // This method will violate the rule, but should not be a property.
      // This method is static but returns a mutable object.
      public static double[] GetDiscountScaleForUpdate()
      {
         return discountScale;
      }

      // This method will violate the rule, but should not be a property.
      // This method performs a conversion.
      public string GetWeekDayString()
      {
         return DateTimeFormatInfo.CurrentInfo.GetDayName(when.DayOfWeek);
      }

      // These methods will violate the rule, and should be properties.
      // They each set or return a piece of the current object's state.

      public DayOfWeek GetWeekDay ()
      {
         return when.DayOfWeek;
      }

      public void  SetCustomerName (string customerName)
      {
         this.customerName = customerName;
      }
      public string GetCustomerName ()
      {
         return customerName;
      }

     public void SetCustomerID (long customerID)
      {
         this.customerID = customerID;
      }

      public long GetCustomerID ()
      {
         return customerID;
      }

      public void SetScheduleTime (DateTime when)
      {
         this.when = when;
      }

      public DateTime GetScheduleTime ()
      {
         return when;
      }

      // Time-consuming method that is called by GetCustomerHistory.
      Appointment[] LoadHistoryFromDB(long customerID)
      {
         ArrayList records = new ArrayList();
         // Load from database.
         return (Appointment[])records.ToArray();
      }
   }
}