专栏首页blackheart的专栏[C#6] 7-索引初始化器

[C#6] 7-索引初始化器

0. 目录

C#6 新增特性目录

1. 老版本的代码

1 private static void Main()
2 {
3     var dictionary = new Dictionary<int, string> {
4         { 1, "Value1" },
5         { 2, "Value2" },
6         { 3, "Value3" }
7     };
8 }

早C#3中引入的集合初始化器,可是让我们用上面的语法来在声明一个字典或者集合的时候立即初始化一些项进去,其实在C#3中这是个语法糖,实质编译后的结果是调用字典或者集合的Add方法逐一添加这些项。但是有一点小小的不直观。先看看这个版的IL吧:

 1 .method private hidebysig static void  Main() cil managed
 2 {
 3   .entrypoint
 4   // Code size       47 (0x2f)
 5   .maxstack  4
 6   .locals init ([0] class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string> dictionary)
 7   IL_0000:  nop
 8   IL_0001:  newobj     instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string>::.ctor()
 9   IL_0006:  dup
10   IL_0007:  ldc.i4.1
11   IL_0008:  ldstr      "Value1"
12   IL_000d:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string>::Add(!0,
13                                                                                                                 !1)
14   IL_0012:  nop
15   IL_0013:  dup
16   IL_0014:  ldc.i4.2
17   IL_0015:  ldstr      "Value2"
18   IL_001a:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string>::Add(!0,
19                                                                                                                 !1)
20   IL_001f:  nop
21   IL_0020:  dup
22   IL_0021:  ldc.i4.3
23   IL_0022:  ldstr      "Value3"
24   IL_0027:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string>::Add(!0,
25                                                                                                                 !1)
26   IL_002c:  nop
27   IL_002d:  stloc.0
28   IL_002e:  ret
29 } // end of method Program::Main

本质是Add方法的调用.C#6引入了一种新语法来进一步的优化这种写法。

2. 索引初始化器

1 private static void Main()
2 {
3     var dictionary = new Dictionary<int, string>
4     {
5         [1] = "Value1",
6         [2] = "Value2",
7         [3] = "Value3"
8     };
9 }

看起来直观许多了吧,其实是一种语法改进。编译结果也有些许差异,如下:

 1 .method private hidebysig static void  Main() cil managed
 2 {
 3   .entrypoint
 4   // Code size       47 (0x2f)
 5   .maxstack  4
 6   .locals init ([0] class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string> dictionary)
 7   IL_0000:  nop
 8   IL_0001:  newobj     instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string>::.ctor()
 9   IL_0006:  dup
10   IL_0007:  ldc.i4.1
11   IL_0008:  ldstr      "Value1"
12   IL_000d:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string>::set_Item(!0,
13                                                                                                                      !1)
14   IL_0012:  nop
15   IL_0013:  dup
16   IL_0014:  ldc.i4.2
17   IL_0015:  ldstr      "Value2"
18   IL_001a:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string>::set_Item(!0,
19                                                                                                                      !1)
20   IL_001f:  nop
21   IL_0020:  dup
22   IL_0021:  ldc.i4.3
23   IL_0022:  ldstr      "Value3"
24   IL_0027:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string>::set_Item(!0,
25                                                                                                                      !1)
26   IL_002c:  nop
27   IL_002d:  stloc.0
28   IL_002e:  ret
29 } // end of method Program::Main

主要差异在于老语法是调用Add方法,新语法是用的索引器的set访问器(set_Item)。

既然是索引,那么就索引就不仅仅只能是int,也可以是string,任意的自定义类型。

3. Example

namespace csharp6
{
    internal class Program
    {
        public class Person
        {
            public string Name { get; set; }
            public int Age { get; set; }

            private Dictionary<string, Address> _cache = new Dictionary<string, Address>();

            public Address this[string name]
            {
                get { return _cache[name]; }
                set { _cache[name] = value; }
            }
        }

        public class Address
        {
            public string Name { get; set; }
            public string Zip { get; set; }
        }

        private static void Main()
        {
            //string索引
            var colorMap = new Dictionary<string, ConsoleColor>
            {
                ["Error"] = ConsoleColor.Red,
                ["Information"] = ConsoleColor.Yellow,
                ["Verbose"] = ConsoleColor.White
            };

            //枚举索引
            var colors = new Dictionary<ConsoleColor, string>
            {
                [ConsoleColor.Red] = "#F00",
                [ConsoleColor.Green] = "#0F0",
            };

            //自定义类型的索引器支持
            Person person = new Person
            {
                Name = "blackheart",
                Age = 1,
                ["home"] = new Address { Name = "北京市", Zip = "100000" },
                ["work"] = new Address { Name = "南京市", Zip = "200000" }
            };

            //自定义类型索引
            var persons = new Dictionary<Person, List<Address>>
            {
                [new Person { Name = "blackheart", Age = 1 }] = new List<Address> {
                    new Address { Name = "北京市", Zip = "100000" }
                },
                [new Person { Name = "blackheart", Age = 1 }] = new List<Address> {
                    new Address { Name = "南京市", Zip = "200000" }
                },
            };
        }
    }
}

4. 总结

从本质来看,[xxx]=yyy这种语法,xxx可以是任意类型,凡是有索引器支持的类型,均可以使用这种语法。简单直接明了。

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • [C#6] 3-null 条件运算符

    0. 目录 C#6 新增特性目录 1. 老版本的代码 1 namespace csharp6 2 { 3 internal class Perso...

    blackheart
  • [C#6] 4-string 插值

    0. 目录 C#6 新增特性目录 1. 老版本的代码 1 internal class Person 2 { 3 public string Na...

    blackheart
  • [C#3] 2-var 类型推断

    1.DEMO static void Main() { var Num = 6; var str = "乱舞春秋"; var dou =...

    blackheart
  • 30分钟?不需要,轻松读懂IL

    先说说学IL有什么用,有人可能觉得这玩意平常写代码又用不上,学了有个卵用。到底有没有卵用呢,暂且也不说什么学了可以看看一些语法糖的实现,或对.net理解更深一点...

    用户1147588
  • [C#6] 3-null 条件运算符

    0. 目录 C#6 新增特性目录 1. 老版本的代码 1 namespace csharp6 2 { 3 internal class Perso...

    blackheart
  • C# 循环的判断会进来几次

    最近有小伙伴告诉我,在循环的判断条件只会计算一次,本金鱼不相信,于是就做了测试,本文记录我做的测试。

    林德熙
  • 《你必须知道的.NET》读书笔记:从Hello World认识IL

      IL是.NET框架中间语言(Intermediate Language)的缩写。使用.NET框架提供的编译器可以直接将源程序编译为.exe或.dll文件,但...

    Edison Zhou
  • [C#3] 2-var 类型推断

    1.DEMO static void Main() { var Num = 6; var str = "乱舞春秋"; var dou =...

    blackheart
  • 学界 | 谷歌大脑提出Adversarial Spheres:从简单流形探讨对抗性样本的来源

    机器之心
  • 进阶篇:以IL为剑,直指async/await

    接上篇:30分钟?不需要,轻松读懂IL,这篇主要从IL入手来理解async/await的工作原理。 先简单介绍下async/await,这是.net 4.5引...

    用户1147588

扫码关注云+社区

领取腾讯云代金券