.NET 中创建支持集合初始化器的类型
对象初始化器和集合初始化器只是语法糖,但是能让你的代码看起来更加清晰。至少能让对象初始化的代码和其他业务执行的代码分开,可读性会好一些。
本文将编写一个类型,可以使用集合初始化器构造这个类型。不只是添加元素的集合初始化器,还有带索引的集合初始化器。
稍微提一下对象初始化器
很普通的类型就可以支持对象初始化器,只需要对象有可以 set 的属性或者可访问的字段即可。
public class Walterlv
{
public string Site { get; set; }
}
初始化时可以使用
var walterlv = new Walterlv
{
Site = "https://walterlv.com",
};
基本上大家编写的类或多或少都会支持对象初始化器,所以本文不会对此谈论更多的内容。
通常的集合初始化器
当你定义一个集合的时候,你会发现你的类型已经天然支持集合初始化器了。比如你定义了下面这个集合:
public class WalterlvCollection : ICollection<Walterlv>
{
// 省略集合定义的代码。
}
那么此集合初始化的代码就可以写成下面这样:
var collection = new WalterlvCollection
{
new Walterlv(),
new Walterlv(),
}
实际上你会发现实现一个 ICollection 是一件非常繁琐的事情。

▲ 实现一个 ICollection 需要实现的方法
最简单的集合初始化器
只是做一个集合初始化器的话并不需要写上面那么多的代码。
实际上,你只需要两个步骤:
- 实现 IEnumerable 接口或任何子接口
- 有一个 Add 方法
就像这样:
public class WalterlvCollection : IEnumerable
{
private readonly List<Walterlv> _list = new List<Walterlv>();
public IEnumerator GetEnumerator()=>_list.GetEnumerator();
public void Add(string site) => _list.Add(new Walterlv { Site = site });
}
于是你就可以像一个一般的集合那样去使用集合初始化器了:
var collection = new WalterlvCollection
{
"https://walterlv.com/",
"https://blog.csdn.net/wpwalter",
};
多个参数的集合初始化器
刚刚我们的例子中 Add 方法只有一个参数,实际上也可以是多个参数。
public class WalterlvCollection : IEnumerable
{
private readonly List<Walterlv> _list = new List<Walterlv>();
public IEnumerator GetEnumerator()=>_list.GetEnumerator();
public void Add(string site, bool includeProtocol) => _list.Add(new Walterlv { Site = site });
}
现在初始化的方法就有点像字典了:
var collection = new WalterlvCollection
{
{ "https://walterlv.com/", true },
{ "https://blog.csdn.net/wpwalter", true },
};
当然你也可以写更多参数,看起来更加丧心病狂。
public class WalterlvCollection : IEnumerable
{
private readonly List<Walterlv> _list = new List<Walterlv>();
public IEnumerator GetEnumerator()=>_list.GetEnumerator();
public void Add(string site, bool includeProtocol, string author)
=> _list.Add(new Walterlv { Site = site });
}
var collection = new WalterlvCollection
{
{ "https://walterlv.com/", true, "walterlv" },
{ "https://blog.csdn.net/wpwalter", true, "walterlv" },
};
带索引集合初始化器
如果你期望的初始化方法是索引,实际上也不需要 Add 方法。只需要增加一个索引的定义即可:
public class WalterlvCollection : IEnumerable
{
private readonly List<Walterlv> _list = new List<Walterlv>();
public IEnumerator GetEnumerator()=>_list.GetEnumerator();
public string this[string site]
{
get => _list.Find(x => x.Site == site).Site;
// 请忽略这里的 Bug,这只是一个语法糖的示例。
set => _list.Add(new Walterlv { Site = value });
}
}
这时,可以使用索引方式的集合初始化器:
var collection = new WalterlvCollection
{
["吕毅"] = "https://walterlv.com/",
["林德熙"] = "https://lindexi.gitee.io/"
};
这是一个可以发挥创造力的语法糖
利用单个和多个参数的集合初始化器,以及带索引的集合初始化器,我们甚至可以用集合初始化器去构造一些看起来不像集合的类型。这又是一波语法糖!
当然有一点值得注意,使用集合初始化器初始化的时候,Add 和 this[] 的初始化是不能同时使用的。
参考资料
事实上微软的官方文档中并没有对集合初始化器的最简实现有多少描述,所以以下的参考实际上并没有用。
- 英文:Object and Collection Initializers (C# Programming Guide) - Microsoft Docs
- 中文:对象和集合初始值设定项(C# 编程指南) - Microsoft Docs
.NET 中创建支持集合初始化器的类型的更多相关文章
- C#中的自动属性、隐式类型var、对象初始化器与集合初始化器、扩展方法
1.自动属性(Auto-Implemented Properties) //以前的写法 .net2.0 private string _userName; public string UserName ...
- C#语法糖之第二篇: 参数默认值和命名参数 对象初始化器与集合初始化器
今天继续写上一篇文章C#4.0语法糖之第二篇,在开始今天的文章之前感谢各位园友的支持,通过昨天写的文章,今天有很多园友们也提出了文章中的一些不足,再次感谢这些关心我的园友,在以后些文章的过程中不断的完 ...
- C#高级知识点概要(3) - 特性、自动属性、对象集合初始化器、扩展方法、Lambda表达式和Linq查询
1.特性(Attributes) 特性(Attributes),MSDN的定义是:公共语言运行时允许你添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型.字段.方法 ...
- C# 3.0 / C# 3.5 对象集合初始化器、匿名类
对象集合初始化器 在 .NET 2.0 中构造一个对象的方法一是提供一个重载的构造函数,二是用默认的构造函数生成一个对象,然后对其属性进行赋值. 在 .NET 3.5/C# 3.0 中,我们有一种更好 ...
- Linq专题之集合初始化器
集合初始化器用来初始化一个集合,和对象初始化器有点类似,都是用一对{}来初始化. using System; using System.Collections.Generic; using Syste ...
- C# 对象初始化器和集合初始化器
/// <summary>/// 图书类/// </summary>public class Book { /// <summary> /// 图书 ...
- [C#6] 7-索引初始化器
0. 目录 C#6 新增特性目录 1. 老版本的代码 private static void Main() { var dictionary = new Dictionary<int, stri ...
- .NET中那些所谓的新语法之一:自动属性、隐式类型、命名参数与自动初始化器
开篇:在日常的.NET开发学习中,我们往往会接触到一些较新的语法,它们相对以前的老语法相比,做了很多的改进,简化了很多繁杂的代码格式,也大大减少了我们这些菜鸟码农的代码量.但是,在开心欢乐之余,我们也 ...
- dotNet中初始化器的使用
dotNet中初始化器的使用 2013年12月7日 13:27 有两类初始化器: 对象初始化器和集合初始化器 比如现在有一个User类: Public class User { public in ...
随机推荐
- js中var a={}什么意思
创建一个变量a, 并给a赋值:{}是一个空的对象,是 new Object();的简写.
- ng-深度学习-课程笔记-15: 循环序列模型(Week1)
1 数学符号(Notation) $ x^{<1>}, x^{<2>}, ..., x^{<t>}, ..., x^{<q>} $ 表示一段输入序列x, ...
- 基于SSH RSA的信任关系
RSA 非对称加密算法 client ---> server 私钥 公钥 1. 客户端生成密钥对 ssh-keygen -t rsa 执行后产生的密钥对会分别追加写到当前用户家目录下的以下文 ...
- 这才是官方的tapable中文文档
起因 搜索引擎搜索tapable中文文档,你会看见各种翻译,点进去一看,确实是官方的文档翻译过来的,但是webpack的文档确实还有很多需要改进的地方,既然是开源的为什么不去github上的tapab ...
- maven nexus私服搭建
1. 下载 wget http://download.sonatype.com/nexus/oss/nexus-2.12.0-01-bundle.tar.gz 2. 解压 tar zxvf nexus ...
- Google发布机器学习平台Tensorflow游乐场~带你玩神经网络(转载)
Google发布机器学习平台Tensorflow游乐场-带你玩神经网络 原文地址:http://f.dataguru.cn/article-9324-1.html> 摘要: 昨天,Google发 ...
- 关于spring框架工作原理的初解
一:spring基本概念 1)struts2是web框架,hibernate是orm框架 2)spring是容器框架,创建bean,维护bean之间的关系 3)spring可以管理web层,持久层,业 ...
- 从0开始学习 GITHUB 系列之「GIT 进阶」【转】
本文转载自:http://stormzhang.com/github/2016/06/16/learn-github-from-zero5/ 版权声明:本文为 stormzhang 原创文章,可以随意 ...
- CentOS7.2 安装nginx-1.10.3
nginx-1.10.3 下载nginx 检查是否安装了依赖库: [root@localhost ~]# rpm -q gcc gcc-4.8.5-11.el7.x86_64 [root@localh ...
- 【重新挂载磁盘空间】Linux系统/home的磁盘空间重新挂载给/root
以下是在centos7版本上做测试 使用如下命令查看磁盘使用情况 ls -lh 文件系统 容量 已用 可用 已用% 挂载点 devtmpfs 3.9G 0 3.9G 0% /dev tmpfs 3.9 ...