CA1024:建議在適當時使用屬性
屬性 | 值 |
---|---|
規則識別碼 | CA1024 |
職稱 | 建議在適當時使用屬性 |
類別 | 設計 |
修正程式是中斷或非中斷 | 中斷 |
預設在 .NET 9 中啟用 | No |
原因
方法的名稱 Get
開頭為 ,不接受任何參數,並傳回不是陣列的值。
根據預設,此規則只會查看外部可見的方法,但這是可設定的。
檔案描述
在大部分情況下,屬性代表數據和方法會執行動作。 屬性會像欄位一樣存取,因此更容易使用。 如果下列其中一個條件存在,方法就是成為屬性的好候選專案:
- 方法不會接受自變數,並傳回 物件的狀態資訊。
- 方法接受單一自變數來設定物件狀態的一部分。
如何修正違規
若要修正此規則的違規,請將 方法變更為 屬性。
隱藏警告的時機
如果方法符合下列其中一個準則,請隱藏此規則的警告。 在這些情況下,方法最好是 屬性。
- 方法無法做為欄位。
- 方法會執行耗時的作業。 方法明顯比設定或取得欄位值所需的時間慢。
- 方法會執行轉換。 存取欄位不會傳回其儲存之數據的已轉換版本。
- 方法
Get
具有可觀察的副作用。 擷取字段的值不會產生任何副作用。 - 執行順序很重要。 設定欄位的值並不依賴其他作業的發生。
- 連續呼叫 方法兩次會建立不同的結果。
- 方法為
static
,但會傳回可由呼叫端變更的物件。 擷取字段的值不允許呼叫端變更欄位所儲存的數據。 - 方法會傳回陣列。
隱藏警告
如果您只想要隱藏單一違規,請將預處理器指示詞新增至原始程式檔以停用,然後重新啟用規則。
#pragma warning disable CA1024
// The code that's violating the rule is on this line.
#pragma warning restore CA1024
若要停用檔案、資料夾或項目的規則,請在組態檔中將其嚴重性設定為 。none
[*.{cs,vb}]
dotnet_diagnostic.CA1024.severity = none
如需詳細資訊,請參閱 如何隱藏程式代碼分析警告。
設定程式代碼以分析
使用下列選項來設定程式代碼基底要執行此規則的部分。
您可以只針對此規則、針對它套用的所有規則,或針對套用至此類別的所有規則,或針對它套用的所有規則,設定此選項。 如需詳細資訊,請參閱 程式代碼品質規則組態選項。
包含特定 API 介面
您可以根據程式代碼基底的存取範圍,設定要執行此規則的部分。 例如,若要指定規則只應該針對非公用 API 介面執行,請將下列機碼/值組新增至 專案中的 .editorconfig 檔案:
dotnet_code_quality.CAXXXX.api_surface = private, internal
範例
下列範例包含數個方法,這些方法應該轉換成屬性,而數個方法不應該因為其行為不如字段。
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 violates 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 violates 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 violates 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 violates the rule, but should not be a property.
// This method performs a conversion.
public string GetWeekDayString()
{
return DateTimeFormatInfo.CurrentInfo.GetDayName(when.DayOfWeek);
}
// These methods 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();
}
}
Public Class Appointment
Shared nextAppointmentID As Long
Shared discountScale As Double() = {5.0, 10.0, 33.0}
Private customerName As String
Private customerID As Long
Private [when] As Date
' Static constructor.
Shared Sub New()
' Initializes the static variable for Next appointment ID.
End Sub
' This method violates 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 Shared Function GetNextAvailableID() As Long
nextAppointmentID += 1
Return nextAppointmentID - 1
End Function
' This method violates the rule, but should not be a property.
' This method performs a time-consuming operation.
' This method returns an array.
Public Function GetCustomerHistory() As Appointment()
' Connect to a database to get the customer's appointment history.
Return LoadHistoryFromDB(customerID)
End Function
' This method violates the rule, but should not be a property.
' This method is static but returns a mutable object.
Public Shared Function GetDiscountScaleForUpdate() As Double()
Return discountScale
End Function
' This method violates the rule, but should not be a property.
' This method performs a conversion.
Public Function GetWeekDayString() As String
Return DateTimeFormatInfo.CurrentInfo.GetDayName([when].DayOfWeek)
End Function
' These methods violate the rule and should be properties.
' They each set or return a piece of the current object's state.
Public Function GetWeekDay() As DayOfWeek
Return [when].DayOfWeek
End Function
Public Sub SetCustomerName(customerName As String)
Me.customerName = customerName
End Sub
Public Function GetCustomerName() As String
Return customerName
End Function
Public Sub SetCustomerID(customerID As Long)
Me.customerID = customerID
End Sub
Public Function GetCustomerID() As Long
Return customerID
End Function
Public Sub SetScheduleTime([when] As Date)
Me.[when] = [when]
End Sub
Public Function GetScheduleTime() As Date
Return [when]
End Function
' Time-consuming method that is called by GetCustomerHistory.
Private Function LoadHistoryFromDB(customerID As Long) As Appointment()
Dim records As ArrayList = New ArrayList()
Return CType(records.ToArray(), Appointment())
End Function
End Class
調試程式中的控件屬性擴充
程序設計人員避免使用屬性的其中一個原因是他們不希望調試程式自動展開它。 例如,屬性可能牽涉到配置大型物件或呼叫 P/Invoke,但實際上可能沒有任何可觀察的副作用。
您可以套用 System.Diagnostics.DebuggerBrowsableAttribute來防止調試程式自動展開屬性。 下列範例顯示這個屬性套用至實例屬性。
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.Diagnostics;
namespace Microsoft.Samples
{
class TestClass
{
// [...]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public LargeObject LargeObject
{
get
{
// Allocate large object
// [...]
}
}
}
}