您的位置:首页 > 其它

.NET 指南:结构的设计

2007-01-29 20:08 260 查看
结构是属于值类型。它们被分配在堆栈或者内嵌空间中并且在它们超出了使用范围时候会被清除。通常,值类型的分配与清除的代价是比较小的;但是,如果它们在需要进行大量的装箱与拆箱操作的开发情节中被使用的时候,它们就会与被用来比较的引用类型一样蹩脚地被完成。关于更多信息,请参考:[C# 编程指南:装箱与拆箱]。

关于值类型和引用类型的附加信息,请参考:[公共类型系统概览]。

不要为结构提供一个默认的构造器。如果结构中定义了一个默认的构造器,那么在创建结构数组的时候,公共语言运行时(CLR)会自动为每个数组元素分别执行默认的构造器。

一些编译器(如 C# 编译器)就不允许结构拥有默认的构造器。

在值类型中实现 System.IEquatable 接口。IEquatable 接口在通过 Equals 方法来检测两个值类型是否相等的时候是首选的。通过使用这个接口,调用者能够避免在装箱和被管理的反射操作时所产生的负面的性能影响。

确保所有实例的数据被设置成零、false,或 null(与适当的一样)时的状态是有效的。通过遵循这个指导方针,你最近被构造的值类型的实例就不会被滞留在一个不可用的状态中。例如,下列结构是错误地被设计的。被参数化的构造器是为了表示能够确保一个有效的状态,但是在创建该结构的一个数组的时候,这个构造器没有被执行。这意味着实例字段 label 被初始化成 null(在 Visual Basic 中是 Nothing),从而该结构的 ToString 方法实现是无效的。

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()
{
// 在 label 的值是 null 的时候,对 label.Length 的访问将会抛出一个 NullReferenceException 异常
return String.Format("Label length: {0} Label: {1} Width: {2} Length: {3}",
label.Length, label, width,length);
}
}
在下列代码范例中,GoodStructure 的设计没有对 label 字段进行相关的假设。并且 ToString 方法被设计成处理一个值为 null 的标签。

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()
{
// 对 label 可能被初始化成 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 进行扩展。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: