.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 ...
随机推荐
- WCF For Silverlight跨域策略
在WCF的根目录下添加跨域文件 <?xml version="1.0" encoding="utf-8" ?> <access-policy& ...
- tp基础补充
ThinkPHP php框架 真实项目开发步骤: 多人同时开发项目,协作开发项目.分工合理.效率有提高(代码风格不一样.分工不好) 测试阶段 上线运行 对项目进行维护.修改.升级(单个人维护项目,十分 ...
- http之工作原理
HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端.HTTP协议采用了请求/响应模型.客户端向服务器发送一个请求报文,请求报文包含请求的方法.URL. ...
- VS2010/MFC编程入门之八(对话框:创建对话框类和添加控件变量)
前两讲中鸡啄米为大家讲解了如何创建对话框资源.创建好对话框资源后要做的就是生成对话框类了.鸡啄米再声明下,生成对话框类主要包括新建对话框类.添加控件变量和控件的消息处理函数等. 因为鸡啄米给大家的例程 ...
- 2017-2018 ACM-ICPC, Asia Daejeon Regional Contest Solution
A:Broadcast Stations 留坑. B:Connect3 题意:四个栈,每次放棋子只能放某个栈的栈顶,栈满不能放,现在给出(1, x) 表示黑子放在第x个栈的第一个位置,白子放在第b个栈 ...
- springcloud14---zuul
package com.itmuch.cloud.study; import org.springframework.boot.SpringApplication; import org.spring ...
- 20155201 2016-2017-2 《Java程序设计》第九周学习总结
20155201 2016-2017-2 <Java程序设计>第九周学习总结 教材学习内容总结 第十六章 整合数据库 JDBC全名JavaDataBaseConnecticity,是Jav ...
- HttpClient 4.5.3 get和post请求
HttpCilent 4.5.3 域名购买.com 后缀好域名 https://mi.aliyun.com/shop/38040 GET请求 CloseableHttpClient httpCilen ...
- js二进制转换十进制
var a = 1010;alert(a.toString(2)); //转成二进制 alert(parseInt( "101110100 ",2)) ;//转成十进制 null
- Ubuntu 安装 Telnet
参考:在 ubuntu 上安裝 telnet service 1.安装: sudo apt-get install xinetd telnetd 2.修改inetd.conf: vim /etc/in ...