当仅需要一个小的数据结构,类提供的功能多于我们需要的功能时,处于性能的考虑,最好使用结构。
为结构定义函数与为类定义函数完全相同。
... {
public double Length;
public double Width;
Dimendions(double length, double width)
...{
Length = length;
Width = width;
}
..........
}
许多方面可以把结构看作是缩小的类。它们基本上与类相同,但是更适合于把一些数据组合起来的场合,它们与类的区别在于
- 结构是值类型,不是引用类型,他们存储在堆栈中或存储为内联(如果它们是另一个保存在堆中的对象的一部分),其生存期的限制与简单数据结构一样。
- 结构不支持继承。
- 结构的构造函数的工作方式有一些区别。尤其是编译器总是提供一个无参的默认构造函数,这是不允许替换的。
- 使用结构可以指定字段如何在内存中布局。
结构是值类型
虽然结构是值类型,但在语法上常常可以把他们当作类来处理。
point.Length = 3 ;
point.Width = 6 ;
注意,因为结构是值类型,new运算符并不分配堆中的内存,而是调用相应的构造函数,根据传送给它的参数,初始化所有字段。也可以这样写:
point.Length = 3 ;
point.Width = 6 ;
如果Dimentions是一个类就会产生编译错误。但对于结构,变量声明实际上是为整个结构分配堆栈中的空间,所以就可以赋值了。
结构遵循其他数据类型都遵循的规则:在使用前所有的元素都必须进行初始化。在结构上调用new运算符,或者给所有的字段分别赋值,结构就完全初始化了(如果结构定义为类的成员字段,在初始化包含对象时,结构就会自动初始化为0)。
结构是值类型,所以会影响性能。正面影响是为结构分配内存时速度非常快。被删除时也很快。负面影响是把结构作为参数来传递或者把一个结构赋给另一结构时会有性能上的损失。结构主要用于小的数据结构,但当把结构作为参数传递给方法时,就应该把它作为ref参数传递,以避免性能损失。
结构和继承
结构不是为继承设计的。不能从一个结构中继承,唯一的例外是结构(和其他C#类型一样)派生于类System.Object。因此结构也可以访问System.Object的方法。在结构中甚至可以重写System.Object中的方法。结构的继承链是每个结构派生于System.ValueType,System.ValueType派生于System.Object。不能为结构提供其他基类:每个结构都派生于ValueType。
结构的构造函数
为结构定义构造函数的方式与为类定义构造函数的方式相同,但不允许定义无参数的构造函数。默认构造函数把所有字段都初始化为0,且总是隐式的给出,即使提供了其他带参数的构造函数也是如此。也不能提供字段的初始值,以此绕过默认构造函数。
部分类
partial关键字允许把类,结构或接口放在多个文件中。有时多个开发人员需要访问同一个类,或者某种类型的代码生成器生成了一个类的某部分,所以把类放在多个文件中是有益的。
... {
public void MethodOne()
...{
}
}
... {
public void MethodTwo()
...{
}
}
编译包含这两个源文件的项目时,会创建一个TheBigClass类,它有MethodOne()和MethodTwo()两个方法。
如果声明类时使用了下面的关键字,这些关键字将应用于同一个类的所有部分:
- public
- private
- protected
- internal
- abstract
- sealed
- 基类
- new
- 一般约束
在嵌套的类型中,只要partial关键字位于class关键字的前面,就可以嵌套部分类。在把部分类编译到类型中时,会合并属性、XML注释、接口、泛型类型的参数属性和成员。
partial class TheBigClass : TheBigBaseClass, IBigClass
... {
public void MethodOne()
...{
}
}
partial class TheBigClass : IOhterBigClass
... {
public void MethodTwo()
...{
}
}
编译后,源文件变成:
[AnotherAttribute]
partial class TheBigClass : TheBigClass , IBigClass, IOhterBigClass
... {
public void MethodOne()
...{
}
public void MethodTwo()
...{
}
}
静态类
如果类只包含静态的方法和属性,该类就是静态类。静态类在功能上与使用私有静态构造函数创建的类相同。不能创建静态类的实例。
... {
public static void Method()
...{
}
}
使用类型名即克进行方法的调用。
Object类
所有的.NET类都派生于System.Object。如果在定义类时没有指定基类,编译器就会自动假定这个类派生于Object。它的重要性在于,除了类自己定义的方法和属性外,还可以访问为Object定义的许多公共或受保护的成员方法。