您的位置:首页 > 编程语言 > C#

C#2008语言特征5----对象和集合初始值语法

2009-03-21 12:40 302 查看
对于这个标题,不同的资料叫法不同,“对象和集合初始值设定项”、“对象和集合初始化器”等跟这里要讲的内容指的都是一会事情。
现在定义一个类Point,里面有两个double类型的私有字段x与y,使用x表示点的横坐标,使用y表示点的横坐标。如果类的定义如下:
class Point
{
private double x;
private double y;
public Point()
{
x = 0.0;
y = 0.0;
}
}
那么生成的Point类的对象的私有字段值只能是0,如果想在对象生成的时候进行字段的初始化,那么必须定义一个带有参数的构造函数,类Point的代码更改为:
class Point
{
private double x;
private double y;
//没有参数的构造函数
public Point()
{
x = 0.0;
y = 0.0;
}
//带有参数的构造函数
public Point(double x, double y)
{
this.x = x;
this.y = y;
}
}
那么就可以使用Point p=new Point(2,3)来生成一个初始值是(2,3)的点。还有一种初始对象的字段而不需要带参数的构造函数的方法,那就是提供类的对字段的封装,可以直接通过属性来操作对象的字段值。类Point的定义代码:
class Point
{
private double x;
private double y;
/// <summary>
/// 私有字段封装为属性
/// </summary>
public double X
{
get { return x; }
set { x = value; }
}
/// <summary>
/// 私有字段封装为属性
/// </summary>
public double Y
{
get { return y; }
set { y = value; }
}

}
现在可以使用语句
Point p = new Point();
p.X = 2.0;
p.Y = 3.0;
来生成一个初始值是(2,3)的类的对象p。好了,现在更进一步,使用自动属性来改写代码。
class Point
{
public double X { get; set; }
public double Y { get; set; }
}
现在可以同样使用代码
Point p = new Point();
p.X = 2.0;
p.Y = 3.0;
来生成一个初始值是(2,3)的类的对象p。可以发现生成一个具有初始值的对象,语法比较复杂,现在c#3.0允许像使用数组一样的初始化方法来初始化一个对象。首先回顾一下数组的初始化方法,数组的初始化方法可以使用语句int [] a={1,2,3};来进行。现在通过Reflector来观察一下这行代码的具体实现过程,发现这行代码被编译为int[] a = new int[] { 1, 2, 3 };现在c#3.0也允许使用int[] a = new int[] { 1, 2, 3 }这样的格式来初始化对象。看例子ObjectInit,在例子中同样定义了一个类Point。类Point的代码是:
namespace ObjectInit
{
class Point
{
public double X { get; set; }
public double Y { get; set; }
}
}
生成对象p的代码是:
namespace ObjectInit
{
class Program
{
static void Main(string[] args)
{
Point p = new Point() { X = 2.0, Y = 3.0 };
Console.WriteLine("点的坐标是x={0},y={1}", p.X, p.Y);
Console.ReadKey();
}
}
}
程序编译被通过,现在看一下这个对象的初始化过程,同样使用Reflector工具反编译,看到main函数生成的代码如图9-12所示:



图9-12
对照图9-12与自己编写的代码,可以发现效果一样,也就是说使用Point p = new Point() { X = 2.0, Y = 3.0 };语法与使用传统的写法效果是一样的。
更加进一步简化,可以将Point p = new Point() { X = 2.0, Y = 3.0 };语句写成Point p = new Point{ X = 2.0, Y = 3.0 };也就是把将new Point()后面的括号省略,可以使用反编译工具参看生成的代码,发现生成的代码是完全相同的。如果把类的定义中的自动属性的代码去掉,而换成直接声明私有的字段,编译程序将会发生“并不包含X的定义”,所以如果要使用初始化语法初始化一个类的对象,必须在类的定义中提供封装属性的get,set方法。
这种语法不但允许编写简单类这样初始化,还允许设置更复杂的嵌套属性类型。譬如,假如再定义的一个矩形类Rectangle,该类有两个属于属于Point类型的叫P1,P2的属性。可以编写下面这样的代码来生成一个新的Rectangle对象,同时设置它的属性。
类Rectangle与类Point的代码:
namespace ObjectInit
{
class Point
{
public double X { get; set; }
public double Y { get; set; }
}
class Rectangle
{
public Point P1 { get; set; }
public Point P2 { get; set; }
}
}
生成Rectangle对象的代码可以写成
namespace ObjectInit
{
class Program
{
static void Main(string[] args)
{
//Point p = new Point() { X = 2.0, Y = 3.0 };
Point p = new Point{ X = 2.0, Y = 3.0 };
Console.WriteLine("点的坐标是x={0},y={1}", p.X, p.Y);

Rectangle re = new Rectangle
{
P1 = new Point { X = 2.0, Y = 3.0 },
P2 = new Point { X = 88, Y = 99 }
};

Console.WriteLine("矩阵点的坐标是x1={0},y1={1}与x2={2},y2={3}", re.P1.X, re.P1.Y, re.P2.X, re.P2.Y);
Console.ReadKey();
}
}
}
注意上面加边框部分的代码,下面使用反编译工具,看看生成矩阵对象re时的代码,如图9-13所示:



图9-13
像上面那样的具有嵌套属性的类的生成,在生成外层类的对象是,有一种更加简单的写法,类Rectangle代码更改如下:
class Rectangle
{
public Point P1 { get; set; }
public Point P2 { get; set; }

public Rectangle()
{
P1 = new Point();
P2 = new Point();
}

}
注意添加了加边框的部分,然后生成Rectangle的代码就可以更改为
Rectangle re = new Rectangle
{
P1 = { X = 2.0, Y = 3.0 },
P2 = { X = 88, Y = 99 }
};
注意加边框部分的语句与前面的代码的对比,使用反编译工具Reflector看一下这段代码的实际执行。如图9-14所示:



图9-14
对比图9-14与图9-13发现代码的执行不完全相同。这是因为对象P1,P2在类Rectangle构造函数里面已经生成,可以使用P2 = { X = 88, Y = 99 }来直接给对象初始化的缘故,不过这种语法只在对类的属性进行初始化的时候才能使用。
像上面的语法不仅仅只对对象可以,对于集合的操作也可以使用。比如以List来举例,以前在生成List对象的时候,初始化语句是:
List<Person> people = new List<Person>();
people.Add( new Person { FirstName = "Scott", LastName = "Guthrie", Age = 32 } );
people.Add( new Person { FirstName = "Bill", LastName = "Gates", Age = 50 } );
people.Add( new Person { FirstName = "Susanne", LastName = "Guthrie", Age = 32 } );
现在可以使用初始话的方法了,完全可以改成如下的写法:
List<Person> people = new List<Person> {
new Person { FirstName = "Scott", LastName = "Guthrie", Age = 32 },
new Person { FirstName = "Bill", LastName = "Gates", Age = 50 },
new Person { FirstName = "Susanne", LastName = "Guthrie", Age = 32 }
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐