.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 ...
随机推荐
- docker——libnetwork插件网络功能
从1.7.0版本开始,Docker正是把网络和存储这两部分的功能都以插件化形式剥离出来,允许用户通过指令来选择不同的后端实现.剥离出来的独立容器网络项目叫libnetwork,从名字就能看出,它希望将 ...
- WdatePicker设置日期范围
设置 结束日期不超过当天日期:设置 开始日期不超过结束日期:设置 开始日期默认显示当月1日的日期,结束日期显示当天日期?<label>开始日期:</label><inpu ...
- 《Java入门第二季》第三章 继承
Java 中的继承1.作用:代码复用. 2.语法:extends关键字. 3.注意点:私有(private)财产(methods.fields)不可继承. Java 中的方法重写 Java 中的继承初 ...
- Win7系统(台式机)设置系统的窗口背景色(豆沙绿色)
Win7系统(台式机)设置系统的窗口背景色(豆沙绿色) 1,桌面->右键->个性化->窗口颜色->高级外观设置->项目选择(窗口).颜色1(L)选择(其它)将色调改为:8 ...
- 20145312《网络对抗》Exp4 恶意代码分析
20145312<网络对抗>Exp4 恶意代码分析 问题回答 1.总结一下监控一个系统通常需要监控什么.用什么来监控. 监控一个系统通常需要监控这个系统的注册表,进程,开放端口,程序服务还 ...
- 解决方案--duilib中edit获得鼠标焦点后右边框被覆盖
用duilib做了一个登录框,用户名的输入使用的是edit控件. XML中是这样写的: <Edit name="subdomain_edit" tipvalue=" ...
- TypeScript 照猫画虎
定义变量类型 const num: number = 1 定义函数参数类型 const init: (p: str) => void = function(param) { alert(para ...
- VMware Vcenter Server 6.0忘记密码
windows 版Vcenter6.0 重置密码首先要登录到安装Vcenter的windows服务器上 用管理员身份打开CMD命令行 进入VMware VCenter的目录 默认是C:\Program ...
- CodeForces 828E DNA Evolution(树状数组)题解
题意:给你一个串k,进行两个操作: “1 a b”:把a位置的字母换成b “2 l r s”:求l到r有多少个字母和s匹配,匹配的条件是这样:从l开始无限循环s形成一个串ss,然后匹配ss和指定区间的 ...
- [PyTorch]论文pytorch复现中遇到的BUG
目录 1. zip argument #1 must support iteration 2. torch.nn.DataParallel 3. model.state_dict() 1. zip a ...