Поделиться через


CA1024: используйте свойства, если это уместно

TypeName

UsePropertiesWhereAppropriate

CheckId

CA1024

Категория

Microsoft.Design

Критическое изменение

Критическое изменение

Причина

Имя открытого или защищенного метода начинается с Get, он не принимает аргументы и возвращает значение, не являющееся массивом.

Описание правила

В большинстве случаев свойства представляют данные, а методы выполняют действия. Со свойствами можно обращаться как c полями, что делает их использование проще. Метод может стать свойством, если соблюдено одно из следующих условий:

  • Он не принимает аргументы и возвращает сведения о состоянии объекта.

  • Он принимает один аргумент для установки некоторой части состояния объекта.

Свойства должны представляться так, как если бы они были полями; если невозможно, метод не следует менять на свойство. Методам следует отдавать предпочтение по отношению к свойствам в следующих ситуациях:

  • Метод выполняет трудоемкую операцию. Этот метод требует ощутимо больше времени, чем его требуется для установки или получения значения поля.

  • Метод выполняет преобразование. Обращение к полю не приводит к возврату преобразованной версии хранящихся в нем данных.

  • Метод 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();
      }
   }
}