结构设计
结构是值类型。 结构是在堆栈上或以内联方式分配的,当结构超出范围时将被释放。 通常情况下,值类型的内存空间分配和释放的开销较小;但在需要大量装箱和取消装箱操作的方案中,值类型的执行性能较引用类型要差。 有关更多信息,请参见装箱和取消装箱(C# 编程指南)。
有关值类型和引用类型的更多信息,请参见 常规类型系统。
不要为结构提供默认的构造函数。
如果某一结构定义了默认构造函数,则在创建该结构的数组时,公共语言运行时会自动对每个数组元素执行该默认构造函数。
有些编译器(如 C# 编译器)不允许结构拥有默认构造函数。
对值类型实现 System.IEquatable`1。
在确定两个值类型是否相等时,IEquatable<T> 要优于 Equals。 通过使用接口,调用方可避免装箱和托管反射的不良性能影响。
确保所有实例数据均设置为零、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。
部分版权所有 2005 Microsoft Corporation。 保留所有权利。
部分版权所有 Addison-Wesley Corporation。 保留所有权利。
设计指引的详细信息,请参阅"框架设计准则: 公约、 成语和可重复使用的模式。网络图书馆"书 Krzysztof Cwalina 和布拉德 · 艾布拉姆斯,2005年艾迪生 - 韦斯利,发表。