• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

C#3.0之对象初始化器(ObjectInitializers)(转载)

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

原文地址:http://ustc.blog.hexun.com/14379535_d.html

概念

在传统的C#中,我们常用两种方法来对一个类(或者结构体)进行初始化,一是采用带有参数的构造函数,另一种则是不采用构造函数,或者构造函数中并没有实际地对字段进行赋值,而是在申请了类的实例之后,手动对它的公共属性进行赋值。下面是一个二维空间的几何点:

 

    public struct Point

    {

        private int xPos, yPos;

 

        public Point(int x, int y)

        {

            xPos = x;

            yPos = y;

        }

 

        public int X

        {

            get { return xPos; }

            set { xPos = value; }

        }

 

        public int Y

        {

            get { return yPos; }

            set { yPos = value; }

        }

 

        public override string ToString()

        {

            return string.Format("[{0}, {1}]", xPos, yPos);

        }

    }

 

传统的初始化手段如下所示:http://ustc.blog.hexun.com

 

    // 手动指定每个属性

    Point firstPoint = new Point();

    firstPoint.X = 10;

    firstPoint.Y = 20;

 

    // 调用自定义的构造函数

    Point anotherPoint = new Point(20, 30);

 

而采用类初始化器的C# 3.0代码则可以写成下面的样子:http://ustc.blog.hexun.com

 

    var yetAnotherPoint = new Point { X = 30, Y = 30 };

    Point finalPoint = new Point { X = 30, Y = 30 };

 

其中第一个是隐式类型变量。这里并没有显式调用Point的构造函数,仅仅是将值设给了公共的XY属性。在这背后,类型的缺省构造函数被调用,紧跟着将值赋给指定的属性。从这一点上说,最后这两个实例实际上就是第一个实例的简化写法。Nocturne Studio

 

如果我们将xPosyPos设定为公共访问,那么我们还可以写出下面的代码(尽管这是很没有道理的做法):Nocturne Studio

 

    var testPoint = new Point { xPos = 100, yPos = 200, X = 300 };

 

这样做的最后结果是xPos最终是300,而yPos200。从这点上来看,对象初始化器是从左到右(呃,或者也可以说从上到下)执行的。这段语句如果用传统的方法来写,就是如下的格式:Nocturne Studio

 

    var testPoint = new Point();

    testPoint.xPos = 100;

    testPoint.yPos = 200;

    testPoint.X = 300;

 

在初始化语法中调用自定义构造函数

前面一个例子中,Point类型初始化时隐式地调用了缺省构造函数。其实我们也被允许直接显式指明使用哪一个构造函数,比如:http://ustc.blog.hexun.com

 

    Point finalPoint = new Point() { X = 30, Y = 30 };

 

当然,也可以不调用缺省的构造函数,而是使用自定义的两个参数的那个构造函数,如下所示:http://ustc.blog.hexun.com

 

    Point finalPoint = new Point(10, 10) { X = 30, Y = 30 };

 

执行的结果,构造函数参数里的10,10被忽略,最终的实例是xPos=30yPos=30。在目前的Point结构体定义中,调用自定义的构造函数没什么太大的用处,反倒显得累赘。然而,我们给Point结构体新增加一个允许在调用时指定一个颜色(通过一个叫做PointColor的枚举类型)的构造函数,那么这样的自定义构造函数与初始化语法之组合就显得很好很强大了。我们把Point结构体改造一下:http://ustc.blog.hexun.com

 

    public enum PointColor

    {

        Tan,

        Indigo,

        Navy

    }

 

    public struct Point

    {

        private int xPos, yPos;

        private PointColor c;

 

        public Point(PointColor color)

        {

            xPos = 0;

            yPos = 0;

            c = color;

        }

 

        public Point(int x, int y)

        {

            xPos = x;

            yPos = y;

            c = PointColor.Tan;

        }

 

        public int X

        {

            get { return xPos; }

            set { xPos = value; }

        }

 

        public int Y

        {

            get { return yPos; }

            set { yPos = value; }

        }

 

        public override string ToString()

        {

            return string.Format("[{0}, {1}, Color = {2}]", xPos, yPos, c);

        }

    }

 

然后回到Main()方法中,我们尝试下面这段语句:http://ustc.blog.hexun.com

 

    Point tanPoint = new Point(PointColor.Tan) { X = 90, Y = 20 };

    Console.WriteLine("Value of Point is: {0}", tanPoint);

 

可以得到如下的结果http://ustc.blog.hexun.com

 

 

 

初始化内部类型

这个说起来很绕口,还是用实例来看。我们定义一个Rectangle类,使用Point类型来代表左上角和右下角两个点的坐标:http://ustc.blog.hexun.com

 

    public class Rectangle

    {

        private Point topLeft = new Point();

        private Point bottomRight = new Point();

 

        public Point TopLeft

        {

            get { return topLeft; }

            set { topLeft = value; }

        }

 

        public Point BottomRight

        {

            get { return bottomRight; }

            set { bottomRight = value; }

        }

 

        public override string ToString()

        {

            return string.Format("[TopLeft: {0}, {1}, BottomRight: {2}, {3}]", topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y);

        }

    }

 

使用对象初始化语法,我们可以创建一个Rectangle的实例并且将它内部的点设置如下:

 

    Rectangle myRect = new Rectangle

    {

        TopLeft = new Point { X = 10, Y = 10 },

        BottomRight = new Point { X = 200, Y = 200 }

    };

 

这个时候,我们就能够体会到它相对于传统方法的好处了。看看我们原先要做的事情:

 

    Rectangle r = new Rectangle();

    Point p1 = new Point();

    p1.X = 10;

    p1.Y = 10;

    r.TopLeft = p1;

    Point p2 = new Point();

    p2.X = 200;

    p2.Y = 200;

    r.BottomRight = p2;

 

嗯,不用我多说什么了吧 ^_^ http://ustc.blog.hexun.com

 

集合初始化Nocturne Studio

与对象初始化语法类似的是集合初始化。这个语法使得我们可以用简单的数组类型来初始化一个泛型容器(比如List<T>)。特别地,这种语法只能用于实现了ICollection<T>接口的类型,包括我们自己实现的自定义泛型容器,因为使用到了Add()方法来将元素插入到集合中。在这个约束之下,System.Collection命名空间下的容器(比如ArrayList)就不能使用这种新语法,因为它们并没有实现所需的接口。看下面的例子:http://ustc.blog.hexun.com

 

    // 初始化一个普通数组

    int[] myIntArray = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

 

    // 初始化一个int型泛型List<>

    List<int> myGenericList = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

 

    // 下面这句是非法的,ArrayList没有实现ICollection<T>接口

    ArrayList myList = new ArrayList { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

 

把我们前面用到的Point类应用进来,比如:http://ustc.blog.hexun.com

 

    List<Point> myPointList = new List<Point>

    {

        new Point {X = 2, Y = 2},

        new Point {X = 3, Y = 3},

        new Point {X = 4, Y = 4}

    };

 

    foreach (var pt in myPointList)

    {

        Console.WriteLine(pt);

    }

 

结果如下:Nocturne Studio

 

 

 

如果到现在你还不能理解这么做的好处,那么看看下面这一组语句吧。这里面用到了嵌套的集合初始化器与对象初始化器。当然你可以尝试一下把它用传统方法来改写,呵呵,那感觉保证让你一爽到底 :-) http://ustc.blog.hexun.com

 

    List<Rectangle> myRectList = new List<Rectangle>

    {

        new Rectangle {TopLeft = new Point {X = 10, Y = 10},

            BottomRight = new Point {X = 200, Y = 200}},

        new Rectangle {TopLeft = new Point {X = 2, Y = 2},

            BottomRight = new Point {X = 100, Y = 100}},

        new Rectangle {TopLeft = new Point {X = 5, Y = 5},

            BottomRight = new Point {X = 90, Y = 75}},

    };

 

    foreach (var r in myRectList)

    {

        Console.WriteLine(r);

    }

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
我是C#上层转到嵌入式和单片机的发布时间:2022-07-10
下一篇:
FluentConsole是一个托管在github的C#开源组件发布时间:2022-07-10
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap