随着 C# 的升级,C# 在语法上对对象的初始化做了不少简化,来看看有没有你不知道的。
数组的初始化
在上一篇罗列数组的小知识的时候,其中也提到了数组的初始化,这时直接引用过来。
int[] arr = new int[3] {1, 2, 3}; // 正儿八经的初始化
int[] arr = new [] {1, 2, 3}; // 简化掉了 int 和数组容量声明
int[] arr = {1, 2, 3}; // 终极简化
字典的两种初始化方式
第二种是 C# 6 的语法,可能很多人不知道。
// 方式一:
var dict = new Dictionary<string, int>
{
{ "key1", 1 },
{ "key2", 20 }
};
// 方式二:
var dict = new Dictionary<string, int>
{
["key1"] = 1,
["key2"] = 20
};
含自定义索引器的对象初始化
这种初始化原理上其实是和上面字典的第二种初始化是一样的。
public class IndexableClass
{
public int this[int index]
{
set
{
Console.WriteLine("{0} was assigned to index {1}", value, index);
}
}
}
var foo = new IndexableClass
{
[0] = 10,
[1] = 20
}
元组的三种初始化方式
前面两种方式很常见,后面一种是 C# 7 的语法,可能有些人不知道。
// 方式一:
var tuple = new Tuple<string, int, MyClass>("foo", 123, new MyClass());
// 方式二:
var tuple = Tuple.Create("foo", 123, newMyClass());
// 方式三:
var tuple = ("foo", 123, new MyClass());
另外补充个小知识,在 C# 7 中,元组的元素可以被解构并命名:
(int number, bool flage) tuple = (123, true);
Console.WriteLine(tuple.number); // 123
Console.WriteLine(tuple.flag); // True
自定义集合类的初始化
只要自定义集合类包含Add
方法,便可以使用下面这种初始化方式为集合初始化元素。
class Program
{
static void Main()
{
var collection = new MyCollection {
"foo", // 对应方法:Add(string item)
{ "bar", 3 }, // 对应方法:Add(string item, int count)
"baz", // 对应方法:Add(string item)
123.45d, // 对应扩展方法:Add(this MyCollection @this, double value)
};
}
}
class MyCollection : IEnumerable
{
private readonly IList _list = new ArrayList();
public void Add(string item)
{
_list.Add(item);
}
public void Add(string item, int count)
{
for (int i = 0; i < count; i++)
{
_list.Add(item);
}
}
public IEnumerator GetEnumerator()
{
return _list.GetEnumerator();
}
}
static class MyCollectionExtensions
{
public static void Add(this MyCollection @this, double value) =>
@this.Add(value.ToString());
}
对象的集合属性初始化
我们知道对集合的初始化必须使用new
创建该集合,不能省略,比如:
// OK
IList<string> synonyms = new List<string> { "c#", "c-sharp" };
// 编译报错,不能省略 new List<string>
IList<string> synonyms = { "c#", "c-sharp" };
但如果该集合作为另外一个类的属性,且该属性有非空默认值,则可以省略new
,比如:
public class Tag
{
public IList<string> Synonyms { get; set; } = new List<string>();
}
var tag = new Tag
{
Synonyms = { "c#", "c-sharp" } // OK
};
能想到和找到的就这么点了,希望以上会对你的编程有所帮助。
目标类型 new 表达式
C# 9.0 引入了目标类型 new
表达式初始化方式。例如下面这个类:
public class Friend
{
public Friend() { }
public Friend(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public string FirstName { get; set; }
public string LastName { get; set; }
}
在 C# 9.0 之前是这样初始化的:
Friend friend = new Friend();
// 或
var friend = new Friend();
Friend friend = new Friend("Thomas", "Huber");
// 或
var friend = new Friend("Thomas", "Huber");
在 C# 9.0 之后,如果赋值语句左边已经声明了类型,则赋值语句右边可以的 new
表达式可以省略类型,例如:
Friend friend = new();
Friend friend = new("Thomas", "Huber");
对于有些场景,这个特性可以使得代码更简洁,例如对属性赋初值:
public ObservableCollection<Friend> Friends { get; } = new();
另外,当赋值语句是元组的解构时,可直接使用 new()
创建语句左边所需元素,各元素的初始值是其类型的默认值,例如:
(int a, int b) t = new();
// 等同于:
(int a, int b) t = (0, 0);
最后,当可以从使用中推断出类型时,也允许省略类型,例如:
var friends = new List<Friend>();
friends.Add(new());