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

来源:互联网 发布:生死狙击刷枪刷枪软件 编辑:程序博客网 时间:2024/04/30 08:55

 

对于这个标题,不同的资料叫法不同,“对象和集合初始值设定项”、“对象和集合初始化器”等跟这里要讲的内容指的都是一会事情。

现在定义一个类Point,里面有两个double类型的私有字段xy,使用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)来生成一个初始值是(23)的点。还有一种初始对象的字段而不需要带参数的构造函数的方法,那就是提供类的对字段的封装,可以直接通过属性来操作对象的字段值。类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;

来生成一个初始值是(23)的类的对象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;

来生成一个初始值是(23)的类的对象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所示:

1

 

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的定义”,所以如果要使用初始化语法初始化一个类的对象,必须在类的定义中提供封装属性的getset方法。

这种语法不但允许编写简单类这样初始化,还允许设置更复杂的嵌套属性类型。譬如,假如再定义的一个矩形类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所示:

2

 

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所示:

3

 

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 }

   };

原创粉丝点击