结构
结构(struct)是一种对数据及功能进行封装的数据结构,与类(class)相比最大不同是:结构是值类型,而类是引用类型。一般结构用于比类(class)更简单的对象。
结构的声明与使用
与类一样,结构可以包含各种成员,如:构造函数、常数、字段、方法、属性、索引器、事件、运算符和嵌套的值类型。同时,结构也可以实现接口。结构的类型声明格式如下:
struct 结构名 [:接口名]
{
...
}
struct
结构类型适合表示如点、矩阵和颜色这样的简单数据结构。例如:
struct Point
{
public double x, y;
public Point (double x, double y) {
this.x = x;
this.y = y;
}
public double R () {
return Math.Sqrt (x * x + y * y);
}
}
class Program
{
static void Main (string[] args) {
Point[] points = new Point[100];
for (int i = 0; i < points.Length; i++) {
points[i] = new Point (i, i * i); // 数值的copy
Console.WriteLine (points[i].R ());
}
}
}
对Point使用结构而不是类,会在成员的存储位置上造成很大的不同。上面的程序中创建并初始化了一个100个单元的数组。如果Point
用类实现,程序就会占用101个分立对象,1个分给数组,另外100个分给每个元素。而用结构来实现Point,程序只会占用1个对象,即1个数组,因而效率较高。
结构在使用时的限制
结构在使用过程中是不支持继承的,在使用结构时,需要注意以下几点:
- 结构不能从其他类型进行继承,只能从接口进行继承。但所有结构都隐含地继承了
Object
。 - 结构不能包括无参数构造方法。可以认为,对于任何结构,系统会自动提供一个无参数的构造方法,该构造方法自动对每个字段赋初始值(
0
,false
,null
等)。 - 如果有构造方法,在构造方法中,必须显示地对每个字段进行赋值,以使得每个字段是确定的。
- 每个字段在定义时,不能给初始值。但
const
常数必须赋以值。 - 结构不能有析构方法。
- 结构成员不能被protected修饰,用为
protected
是与继承相关的。 - 结构类型的变量不能使用
==
来进行比较判断,除非之中定义了运算符==
。
使用结构时,结构的实例化可以不使用new
运算符。如果不使用new
,那么所有的字段都是默认初始值(0
,false
,null
等)。如果使用new
,则可以调用相应的构造方法。总之,结构的实例化可以使用new
,也可以不使用new
,而类的实例化必须使用new
。
枚举
枚举(enum)应用于有多个选择情况的场合,枚举类型为一组符号常数提供了一个类型名称。在枚举中的每个成员实际上是一个符号常数。例如:
enum LightColor
{
Red, Yellow, Green
}
声明了一个枚举类型Color
,它表示3中可能情况:Red
,Yellow
,Green
。这里的3个值实际上是3个整数0
,1
,2
,但与整数相比,使用枚举使程序的可读性更好,并且容易检查出错误。
枚举的声明
声明枚举类型使用关键字enum
。声明的基本格式如下:
enum 枚举名 [:基本类型名]
{
枚举成员 [ = 常数表达式],
...
}
每个枚举类型都有一个相应的整数类型,称为枚举类型的基本类型(underlying type)。一个枚举声明可以显示地声明为byte
,sbyte
,short
,ushort
,int
,uint
,long
或ulong
中的一个基本类型。注意,不能用char作为基本类型。如果没有显示声明基本类型,则默认为int
。
隐式赋值按以下规则来确定值:
enum Color
{
Red,
Green = 10,
Blue,
Max = Blue
}
其中Red
的值为0
,Green
的值为10
,Blue
的值为11
,Max
的值为11
。
枚举成员前面都不能显示地使用修饰符。每个枚举成员都是隐含const的,其值不能改变;每个成员隐含都是public
的,其访问控制不受限制;每个成员隐含都是static
的,直接用枚举类型名进行访问。例如:
enum LightColor
{
Red, Yellow, Green
}
class TrafficLight
{
public static void WhatInfo(LightColor color) {
switch (color) {
case LightColor.Red:
Console.WriteLine("Stop!");
break;
case LightColor.Yellow:
Console.WriteLine("Warning!");
break;
case LightColor.Green:
Console.WriteLine("Go!");
break;
default:
break;
}
}
public static LightColor GetRandomColor() {
Random rng = new Random();
int num = rng.Next (3);
return (LightColor)num;
}
}
class Test
{
static void Main (string[] args) {
LightColor c = TrafficLight.GetRandomColor();
Console.WriteLine(c.ToString());
TrafficLight.WhatInfo(c);
}
}
枚举量的运算
每个枚举类型自动从类System.Enum
派生。因此,Enum
类的方法和属性可以被用在一个枚举类型的数值上。对于枚举类型,可以使用整数类型所能用的大部分运算符,包括:==, !=, <, >, <=, >=, +, -, ^, &, |, ~, ++, --, sizeof
。
枚举类型和整数类型之间的转换要使用强制类型转换。有一个特例是,常数0可以隐式的转换为任何枚举类型。
枚举类型也可以与字符串相互转换。枚举类型的ToString()
方法能够得到一个字符串,这个字符串是相对应的枚举成员的名字,如上例用到的Console.WriteLine(c.ToString());
。
System.Enum
的Parse()
方法可以将枚举常数字符串转换为等效的枚举对象。Parse()
方法格式如下:
public static object Parse(Type, string);
例如:
Color c = (Color)Enum.Parse(typedef(Color), "Red");