結構設計
結構為實值型別, 且配置在堆疊上或內嵌,而在超出範圍時會解除配置。 一般來說,實值型別的配置成本要比解除配置來得低,但是,如果在需要大量 Boxing 和 Unboxing 的案例中使用實值型別時,其執行效能相較於參考型別會低很多。 如需詳細資訊,請參閱Boxing 和 Unboxing (C# 程式設計手冊)。
如需實值型別和參考型別的詳細資訊,請參閱一般型別系統。
不要為結構提供預設的建構函式
如果結構會在建立結構陣列時定義預設建構函式,則 Common Language Runtime 會自動在每一個陣列元素上執行預設建構函式。
類似 C# 編譯器的某些編譯器不允許結構擁有預設建構函式。
一定要在實值型別上實作 System.IEquatable`1
在判斷兩個實值型別是否相等時,IEquatable<T> 會優先於 Equals。 使用介面之後,呼叫端可避免 Boxing 和 Managed 反映 (Reflection) 所發生的負面效能影響。
務必要確定當所有執行個體資料適當地設定為零、false 或 null 的狀態是有效的
在遵循此方針之後,新建構的實值型別執行個體就不會處於無法使用的狀態。 例如,下列結構的設計不正確, 參數化的建構函式應該是要確保有效的狀態,但是當建立此結構的陣列時,未執行此建構函式。 這表示,執行個體欄位 label 會初始化為 null (Visual Basic 中為 Nothing),這對於此結構的 ToString 實作是無效的。
Public Structure BadStructure
Private label As String
Private width As Integer
Private length As Integer
Public Sub New(ByVal labelValue As String, ByVal widthValue As Integer, ByVal lengthValue As Integer)
If ((labelValue = Nothing) _
OrElse (labelValue.Length = 0)) Then
Throw New ArgumentNullException("label")
End If
label = labelValue
width = widthValue
length = lengthValue
End Sub
Public Overrides Function ToString() As String
' Accessing label.Length throws a NullReferenceException
' when label is null.
Return String.Format("Label length: {0} Label: {1} Width: {2} Length: {3}", label.Length, label, width, length)
End Function
End Structure
public struct BadStructure
{
string label;
int width;
int length;
public BadStructure (string labelValue, int widthValue, int lengthValue)
{
if (labelValue == null || labelValue.Length ==0)
{
throw new ArgumentNullException("label");
}
label = labelValue;
width = widthValue;
length = lengthValue;
}
public override string ToString()
{
// Accessing label.Length throws a NullReferenceException
// when label is null.
return String.Format("Label length: {0} Label: {1} Width: {2} Length: {3}",
label.Length, label, width,length);
}
}
在下列程式碼範例中,GoodStructure 的設計不會對 label 欄位的狀態做任何假設。 ToString 方法的設計目的,是要處理 null 標籤。
Public Structure GoodStructure
Private label As String
Private width As Integer
Private length As Integer
Public Sub New(ByVal labelValue As String, ByVal widthValue As Integer, ByVal lengthValue As Integer)
label = labelValue
width = widthValue
length = lengthValue
End Sub
Public Overrides Function ToString() As String
' Handle the case where label might be
' initialized to null;
Dim formattedLabel As String = label
Dim formattedLableLength As Integer
If (formattedLabel = Nothing) Then
formattedLabel = "<no label value specified>"
formattedLableLength = 0
Else
formattedLableLength = label.Length
End If
Return String.Format("Label Length: {0} Label: {1} Width: {2} Length: {3}", formattedLableLength, formattedLabel, width, length)
End Function
End Structure
public struct GoodStructure
{
string label;
int width;
int length;
public GoodStructure (string labelValue, int widthValue, int lengthValue)
{
label = labelValue;
width = widthValue;
length = lengthValue;
}
public override string ToString()
{
// Handle the case where label might be
// initialized to null;
string formattedLabel = label;
int formattedLableLength;
if (formattedLabel == null)
{
formattedLabel = "<no label value specified>";
formattedLableLength = 0;
} else
{
formattedLableLength = label.Length;
}
return String.Format("Label Length: {0} Label: {1} Width: {2} Length: {3}",
formattedLableLength, formattedLabel, width, length);
}
}
請勿明確擴充 System.ValueType
某些編譯器不允許您擴充 ValueType。
Portions Copyright 2005 Microsoft Corporation. All rights reserved.
Portions Copyright Addison-Wesley Corporation. All rights reserved.
設計指引的詳細資訊,請參閱"框架設計準則:公約、 成語和可重複使用的模式。網路圖書館"書 Krzysztof Cwalina 和布拉德 · 艾布拉姆斯,2005年艾迪生 - 衛斯理,發表。