专栏首页大内老A深入理解C# 3.x的新特性(5):Object Initializer 和 Collection Initializer

深入理解C# 3.x的新特性(5):Object Initializer 和 Collection Initializer

深入理解C# 3.x的新特性系列自开篇以后,已经有两个月了。在前面的章节中,我们先后深入讨论了C# 3.x新引入的一些列新特性:Anomynous TypeExtension MethodLambda ExpressionAutomatically Implemented Property,今天我们来讨论本系列的涉及的另外两个简单的Feature: Object Initializer 和 Collection Initializer。

一、 为什么要引入Object Initializer 和 Collection Initializer

在创建一个具有较多属性的对象时,我们一定经常遇到这样的状况:为了尽量地使我们的Code更加简洁,我们试图调用一个适合的Constructor使得对象在创建过程中就可以为所需的属性进行初始化,但是往往我们找不到这样“完美”的Constructor都能够匹配我们需要进行初始化的属性列表。于是我们通常调用一个相对适合的Constructor创建我们需要的对象,对于没能在Constructor中初始化的Field或者Property,再一次对其进行赋值。现在我们有了一个好的办法有效地解决了这个问题,那就是Object Initializer。

上面说的对于一个一般对象的创建和初始化,现在说说我们经常使用的实现了接口System.Collections.IEnumerable的Collection的创建和初始化。对于这样的对象,我们一般先通过Constructor创建该对象,然后通过Add方法或者其他的方式将添加我们所需Element。现在我们可以通过Collection Initializer将这个两个过程合二为一。

接下来我们就来介绍如果使用Object Initializer和Collection Initializer,以及他们背后的本质是什么:Compiler到底在编译的时候为我们做的什么。

二、 Object Initializer的使用和本质

Object Initializer的使用很简单:在通过new 关键字创建对象的时候,将所需的Field/Proeprty的复制置于Type name后的{}中。比如:

class Program
    {
        static void Main(string[] args)
        {
            Vector v = new Vector { X = 1, Y = 2 };            
        }
    }

    class Vector
    {
        public double X
        {
            get;
            set;
        }

        public double Y
        {
            get;
            set;
        }
}

注:对于Vector的定义,还使用到了C#3.x的另一个新的特性:Automatically Implemented Proeprty

在上面的例子中,我们通过一句代码(Vector v = new Vector { X = 1, Y = 2 }; )实现对Vector对象的创建和对X&Y的初始化。

在本系列开始的时候,我就一直在强调: C# 3.x这些Feature仅仅是基于一种Programming Language层面的新特性而已,这些特性通过Programming Language对应的Compiler在编译过程添加一些辅助的Code来实现。对于上面这句简单的Code(Vector v = new Vector { X = 1, Y = 2 }; ),通过编译,将会下面这个样子:

Vector <>g__initLocal0 = new Vector();
<>g__initLocal0.X = 1;
<>g__initLocal0.Y = 2;
Vector v = <>g__initLocal0;

通过对上面一段代码的分析,我们可以归纳出Compiler通过以下3个步骤实现Object Initializer。

  • 调用对应Class的对应的Constructor创建一个临时对象。
  • 根据在{}的赋值语句对临时对象对应的Field/Property进行赋值。
  • 将这个临时对象赋值给你创建的对象。

三、Collection Initializer的使用与本质

Collection Initializer将Collection对象的创建和对于Element的初始化合二为一,他的使用和Object Initializer很类似:将Element List直接加个Class name后的{}中:

IList<string> list = new List<string> { "Zhang San", "Li Si", "Wang Wu" };

和分析Object Initializer的本质一样,我们之后看看通过Compiler变异后的Code是什么样子,就会对Collection Initializer的实现有一个全面的了解:

List<string> <>g__initLocal0 = new List<string>();

<>g__initLocal0.Add("Zhang San");

<>g__initLocal0.Add("Li Si");

<>g__initLocal0.Add("Wang Wu");

IList<string> list = <>g__initLocal0;

Collection Initializer的实现和Object Initializer很类似:

  • 调用对应Class的Default Constructor(无参的)创建一个临时对象。
  • 根据在{}的赋值语句,通过调用Add方法添加相应的Element。
  • 将这个临时对象赋值给你创建的对象。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 从yield关键字看IEnumerable和Collection的区别

    C#的yield关键字由来以久,如果我没有记错的话,应该是在C# 2.0中被引入的。相信大家此关键字的用法已经了然于胸,很多人也了解yield背后的“延迟赋值”...

    蒋金楠
  • 深入理解C# 3.x的新特性(2):Extension Method[下篇]

    四、Extension Method的本质 通过上面一节的介绍,我们知道了在C#中如何去定义一个Extension Method:它是定义在一个Static c...

    蒋金楠
  • WCF中的Binding模型之六(完结篇):从绑定元素认识系统预定义绑定

    由于绑定对象由一系列有序的绑定元素组成,绑定元素最终决定着信道栈中信道的组成,而信道的组成最终又决定了信道栈对消息进行处理的方式和能力,所有要确定绑定的特性和能...

    蒋金楠
  • BZOJ3261: 最大异或和(可持久化trie树)

    attack
  • [leetcode数组系列1]两数之和

    我们需要在一个数组nums中寻找两个数,然后呢这个两个数之和需要等于目标的值。ok,我的外层循环从第一个数开始遍历,内层循环从第二个数遍历,如果这两个数和等于目...

    我是程序员小贱
  • 普通Arduino控制GoPro全系列

    该库具有尝试连接的方法GoPRO.begin(ssid, pass)。实际上,如果以其他方式建立连接,则此函数返回。truefalse

    云深无际
  • 【回溯算法】回溯,从入门到入土,七道试题精选、精讲、精练

    前期准备,要玩得转回溯,递归的基础还是要有的,所以前些日子我就先把递归部分给办了。 【LeetCode】递归 原理入门+复杂度计算+练手试题

    看、未来
  • 十道简单算法题

    前言 最近在回顾以前使用C写过的数据结构和算法的东西,发现自己的算法和数据结构是真的薄弱,现在用Java改写一下,重温一下。 只能说慢慢积累吧~下面的题目难度都...

    Java3y
  • LeetCode动态规划上之递归+记忆化搜索+DP逐步进阶(上)

    给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

    公众号guangcity
  • BZOJ4260: Codechef REBXOR (01Tire树)

    attack

扫码关注云+社区

领取腾讯云代金券