CA1024: 適切な場所にプロパティを使用します

TypeName

UsePropertiesWhereAppropriate

CheckId

CA1024

分類

Microsoft.Design

互換性に影響する変更点

あり

原因

パブリック メソッドまたはプロテクト メソッドに、Get で始まる名前が付けられ、パラメーターは使用されていません。また、配列ではない値を返します。

規則の説明

ほとんどの場合、プロパティはデータを表し、メソッドはアクションを実行します。プロパティにはフィールドと同様にアクセスできるため、使用が簡単です。次のいずれかの条件に該当する場合は、メソッドをプロパティに変更できる可能性があります。

  • 引数を受け取らず、オブジェクトのステータス情報を返す場合。

  • オブジェクトの状態の一部を設定する単一の引数を受け取る場合。

プロパティは、フィールドと同様に動作します。メソッドで同様に動作できない場合、プロパティに変更しないでください。次のような場合、プロパティよりもメソッドの方が適しています。

  • メソッドで時間のかかる操作を実行する場合。メソッドは、フィールド値の設定または取得に必要な時間よりも、明らかに長くかかります。

  • メソッドで変換を実行する場合。フィールドへのアクセスでは、格納データの変換されたバージョンは返されません。

  • Get メソッドに明らかな副作用がある場合。フィールド値の取得には副作用はありません。

  • 実行順序が重要となる場合。フィールド値の設定は、発生した他の操作に依存しません。

  • メソッドを 2 回続けて呼び出した場合に、異なる結果が生じるとき。

  • メソッドが静的でも、呼び出し元によって変更できるオブジェクトを返す場合。フィールド値の取得の場合、呼び出し元は、フィールドに格納されているデータを変更できません。

  • メソッドが配列を返す場合。

違反の修正方法

この規則違反を修正するには、メソッドをプロパティに変更します。

警告を抑制する状況

メソッドが上記で列挙した基準のいずれかに適合する場合、この規則からの警告を抑制します。

デバッガーでのプロパティの展開の制御

プログラマがプロパティの使用を避ける理由の 1 つは、デバッガーがプロパティを自動展開するのを好まないためです。たとえば、プロパティが大きなオブジェクトの割り当てや P/Invoke の呼び出しに関連していても、実際には明らかな影響を及ぼさない場合があります。

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();
      }
   }
}