使用 C# 可以在单条语句中实例化对象或集合并执行成员分配。

对象初始值设定项
使用对象初始值设定项,你可以在创建对象时向对象的任何可访问字段或属性分配值,而无需调用后跟赋值语句行的构造函数。 利用对象初始值设定项语法,你可为构造函数指定参数或忽略参数(以及括号语法)。 以下示例演示如何使用具有命名类型 Cat 的对象初始值设定项以及如何调用无参数构造函数。 请注意,自动实现的属性在 Cat 类中的用法。
public class Cat
{
public int Age { get; set; }
public string Name { get; set; } public Cat()
{
} public Cat(string name)
{
this.Name = name;
}
}
Cat cat = new Cat { Age = , Name = "Fluffy" };
Cat sameCat = new Cat("Fluffy"){ Age = };

对象初始值设定项语法允许你创建一个实例,然后将具有其分配属性的新建对象指定给赋值中的变量。

从 C# 6 开始,除了分配字段和属性外,对象初始值设定项还可以设置索引器。 请思考这个基本的 Matrix 类:

public class Matrix
{
private double[,] storage = new double[, ]; public double this[int row, int column]
{
// 嵌入的数组将酌情抛出超出范围的异常。
get { return storage[row, column]; }
set { storage[row, column] = value; }
}
}

可以使用以下代码初始化标识矩阵:

var identity = new Matrix
{
[, ] = 1.0,
[, ] = 0.0,
[, ] = 0.0, [, ] = 0.0,
[, ] = 1.0,
[, ] = 0.0, [, ] = 0.0,
[, ] = 0.0,
[, ] = 1.0,
};

包含可访问资源库的任何可访问索引器都可以用作对象初始值设定项中的表达式之一,这与参数的数量或类型无关。 索引参数构成左侧赋值,而表达式右侧是值。 例如,如果 IndexersExample 具有适当的索引器,则这些都是有效的:

var thing = new IndexersExample {
name = "object one",
[] = '',
[] = '',
[] = '',
Size = Math.PI,
['C',] = "Middle C"
}

对于要进行编译的前面的代码,IndexersExample 类型必须具有以下成员:

public string name;
public double Size { set { ... }; }
public char this[int i] { set { ... }; }
public string this[char c, int i] { set { ... }; }
 
具有匿名类型的对象初始值设定项
尽管对象初始值设定项可用于任何上下文中,但它们在 LINQ 查询表达式中特别有用。 查询表达式常使用只能通过使用对象初始值设定项进行初始化的匿名类型,如下面的声明所示。
var pet = new { Age = , Name = "Fluffy" };

利用匿名类型,LINQ 查询表达式中的 select 子句可以将原始序列的对象转换为其值和形状可能不同于原始序列的对象。 如果你只想存储某个序列中每个对象的部分信息,则这很有用。 在下面的示例中,假定产品对象 (p) 包含很多字段和方法,而你只想创建包含产品名和单价的对象序列。

var productInfos =
from p in products
select new { p.ProductName, p.UnitPrice };

执行此查询时,productInfos 变量将包含一系列对象,这些对象可以在 foreach 语句中进行访问,如下面的示例所示:

foreach(var p in productInfos){...}

新的匿名类型中的每个对象都具有两个公共属性,这两个属性接收与原始对象中的属性或字段相同的名称。 你还可在创建匿名类型时重命名字段;下面的示例将 UnitPrice 字段重命名为 Price

select new {p.ProductName, Price = p.UnitPrice};
 
集合初始值设定项

在初始化实现 IEnumerable 的集合类型和初始化使用适当的签名作为实例方法或扩展方法的 Add 时,集合初始值设定项允许指定一个或多个元素初始值设定项。 元素初始值设定项可以是简单的值、表达式或对象初始值设定项。 通过使用集合初始值设定项,无需指定多个调用;编译器将自动添加这些调用。

下面的示例演示了两个简单的集合初始值设定项:

List<int> digits = new List<int> { , , , , , , , , ,  };
List<int> digits2 = new List<int> { + , % , MakeInt() };

下面的集合初始值设定项使用对象初始值设定项来初始化上一个示例中定义的 Cat 类的对象。 请注意,各个对象初始值设定项分别括在大括号中且用逗号隔开。

List<Cat> cats = new List<Cat>
{
new Cat{ Name = "Sylvester", Age= },
new Cat{ Name = "Whiskers", Age= },
new Cat{ Name = "Sasha", Age= }
};

如果集合的 Add 方法允许,则可以将 null 指定为集合初始值设定项中的一个元素。

List<Cat> moreCats = new List<Cat>
{
new Cat{ Name = "Furrytail", Age= },
new Cat{ Name = "Peaches", Age= },
null
};

如果集合支持读取/写入索引,可以指定索引元素。

var numbers = new Dictionary<int, string>
{
[] = "seven",
[] = "nine",
[] = "thirteen"
};

前面的示例生成调用 Item[TKey] 以设置值的代码。 从 C# 6 开始,可以使用以下语法初始化字典和其他关联容器。 请注意,它使用具有多个值的对象,而不是带括号和赋值的索引器语法:

var moreNumbers = new Dictionary<int, string>
{
{, "nineteen" },
{, "twenty-three" },
{, "forty-two" }
};

示例

下例结合了对象和集合初始值设定项的概念。

 public class InitializationSample
{
public class Cat
{
// 自动属性
public int Age { get; set; }
public string Name { get; set; } public Cat() { } public Cat(string name)
{
Name = name;
}
} public static void Main()
{
Cat cat = new Cat { Age = , Name = "Fluffy" };
Cat sameCat = new Cat("Fluffy"){ Age = }; List<Cat> cats = new List<Cat>
{
new Cat { Name = "Sylvester", Age = },
new Cat { Name = "Whiskers", Age = },
new Cat { Name = "Sasha", Age = }
}; List<Cat> moreCats = new List<Cat>
{
new Cat { Name = "Furrytail", Age = },
new Cat { Name = "Peaches", Age = },
null
}; // 打印结果
System.Console.WriteLine(cat.Name); foreach (Cat c in cats)
System.Console.WriteLine(c.Name); foreach (Cat c in moreCats)
if (c != null)
System.Console.WriteLine(c.Name);
else
System.Console.WriteLine("List element has null value.");
}
// 输出:
//Fluffy
//Sylvester
//Whiskers
//Sasha
//Furrytail
//Peaches
//List element has null value.
}

下面的示例展示了实现 IEnumerable 且包含具有多个参数的 Add 方法的一个对象,它使用在列表中每项具有多个元素的集合初始值设定项,这些元素对应于 Add 方法的签名。

 public class FullExample
{
class FormattedAddresses : IEnumerable<string>
{
private List<string> internalList = new List<string>();
public IEnumerator<string> GetEnumerator() => internalList.GetEnumerator(); System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => internalList.GetEnumerator(); public void Add(string firstname, string lastname,
string street, string city,
string state, string zipcode) => internalList.Add(
$@"{firstname} {lastname}
{street}
{city}, {state} {zipcode}"
);
} public static void Main()
{
FormattedAddresses addresses = new FormattedAddresses()
{
{"John", "Doe", "123 Street", "Topeka", "KS", "" },
{"Jane", "Smith", "456 Street", "Topeka", "KS", "" }
}; Console.WriteLine("Address Entries:"); foreach (string addressEntry in addresses)
{
Console.WriteLine("\r\n" + addressEntry);
}
} /*
* 输出: Address Entries: John Doe
123 Street
Topeka, KS 00000 Jane Smith
456 Street
Topeka, KS 00000
*/
}

Add 方法可使用 params 关键字来获取可变数量的自变量,如下例中所示。 此示例还演示了索引器的自定义实现,以使用索引初始化集合。

 public class DictionaryExample
{
class RudimentaryMultiValuedDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, List<TValue>>>
{
private Dictionary<TKey, List<TValue>> internalDictionary = new Dictionary<TKey, List<TValue>>(); public IEnumerator<KeyValuePair<TKey, List<TValue>>> GetEnumerator() => internalDictionary.GetEnumerator(); System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => internalDictionary.GetEnumerator(); public List<TValue> this[TKey key]
{
get => internalDictionary[key];
set => Add(key, value);
} public void Add(TKey key, params TValue[] values) => Add(key, (IEnumerable<TValue>)values); public void Add(TKey key, IEnumerable<TValue> values)
{
if (!internalDictionary.TryGetValue(key, out List<TValue> storedValues))
internalDictionary.Add(key, storedValues = new List<TValue>()); storedValues.AddRange(values);
}
} public static void Main()
{
RudimentaryMultiValuedDictionary<string, string> rudimentaryMultiValuedDictionary1
= new RudimentaryMultiValuedDictionary<string, string>()
{
{"Group1", "Bob", "John", "Mary" },
{"Group2", "Eric", "Emily", "Debbie", "Jesse" }
};
RudimentaryMultiValuedDictionary<string, string> rudimentaryMultiValuedDictionary2
= new RudimentaryMultiValuedDictionary<string, string>()
{
["Group1"] = new List<string>() { "Bob", "John", "Mary" },
["Group2"] = new List<string>() { "Eric", "Emily", "Debbie", "Jesse" }
};
RudimentaryMultiValuedDictionary<string, string> rudimentaryMultiValuedDictionary3
= new RudimentaryMultiValuedDictionary<string, string>()
{
{"Group1", new string []{ "Bob", "John", "Mary" } },
{ "Group2", new string[]{ "Eric", "Emily", "Debbie", "Jesse" } }
}; Console.WriteLine("Using first multi-valued dictionary created with a collection initializer:"); foreach (KeyValuePair<string, List<string>> group in rudimentaryMultiValuedDictionary1)
{
Console.WriteLine($"\r\nMembers of group {group.Key}: "); foreach (string member in group.Value)
{
Console.WriteLine(member);
}
} Console.WriteLine("\r\nUsing second multi-valued dictionary created with a collection initializer using indexing:"); foreach (KeyValuePair<string, List<string>> group in rudimentaryMultiValuedDictionary2)
{
Console.WriteLine($"\r\nMembers of group {group.Key}: "); foreach (string member in group.Value)
{
Console.WriteLine(member);
}
}
Console.WriteLine("\r\nUsing third multi-valued dictionary created with a collection initializer using indexing:"); foreach (KeyValuePair<string, List<string>> group in rudimentaryMultiValuedDictionary3)
{
Console.WriteLine($"\r\nMembers of group {group.Key}: "); foreach (string member in group.Value)
{
Console.WriteLine(member);
}
}
} /*
* 输出: Using first multi-valued dictionary created with a collection initializer: Members of group Group1:
Bob
John
Mary Members of group Group2:
Eric
Emily
Debbie
Jesse Using second multi-valued dictionary created with a collection initializer using indexing: Members of group Group1:
Bob
John
Mary Members of group Group2:
Eric
Emily
Debbie
Jesse Using third multi-valued dictionary created with a collection initializer using indexing: Members of group Group1:
Bob
John
Mary Members of group Group2:
Eric
Emily
Debbie
Jesse
*/
}

C#3.0新增功能06 对象和集合初始值设定项的更多相关文章

  1. C#对象和集合初始值设定项

    对象初始值设定项 使用对象初始值设定项,你可以在创建对象时向对象的任何可访问字段或属性分配值,而无需调用后跟赋值语句行的构造函数. 利用对象初始值设定项语法,你可为构造函数指定参数或忽略参数(以及括号 ...

  2. C#3.0新特性:隐式类型、扩展方法、自动实现属性,对象/集合初始值设定、匿名类型、Lambda,Linq,表达式树、可选参数与命名参数

    一.隐式类型var 从 Visual C# 3.0 开始,在方法范围中声明的变量可以具有隐式类型var.隐式类型可以替代任何类型,编译器自动推断类型. 1.var类型的局部变量必须赋予初始值,包括匿名 ...

  3. C#2.0新增功能06 协变和逆变

    连载目录    [已更新最新开发文章,点击查看详细] 在 C# 中,协变和逆变能够实现数组类型.委托类型和泛型类型参数的隐式引用转换. 协变保留分配兼容性,逆变则与之相反. 以下代码演示分配兼容性.协 ...

  4. C# WinForm程序添加引用后调用静态方法时报“Interfaces_Helper.Global”的类型初始值设定项引发异常。---> System.NullReferenceException: 未将对象引用设置到对象的实例。

    出现原因: 因为Global类初始化某个静态变量时没有成功则会抛 System.NullReferenceException 异常,具体代码: public static string connstr ...

  5. C#3.0新增功能03 隐式类型本地变量

    连载目录    [已更新最新开发文章,点击查看详细] 从 Visual C# 3.0 开始,在方法范围内声明的变量可以具有隐式“类型”var. 隐式类型本地变量为强类型,就像用户已经自行声明该类型,但 ...

  6. C#3.0新增功能02 匿名类型

    连载目录    [已更新最新开发文章,点击查看详细] 匿名类型提供了一种方便的方法,可用来将一组只读属性封装到单个对象中,而无需首先显式定义一个类型. 类型名由编译器生成,并且不能在源代码级使用. 每 ...

  7. C#3.0新增功能09 LINQ 基础05 使用 LINQ 进行数据转换

    连载目录    [已更新最新开发文章,点击查看详细] 语言集成查询 (LINQ) 不只是检索数据. 它也是用于转换数据的强大工具. 通过使用 LINQ查询,可以使用源序列作为输入,并通过多种方式对其进 ...

  8. C#3.0新增功能09 LINQ 基础08 支持 LINQ 的 C# 功能

    连载目录    [已更新最新开发文章,点击查看详细] 查询表达式 查询表达式使用类似于 SQL 或 XQuery 的声明性语法来查询 IEnumerable 集合. 在编译时,查询语法转换为对 LIN ...

  9. C#6.0 新增功能

    连载目录    [已更新最新开发文章,点击查看详细] C# 6.0 版本包含许多可提高开发人员工作效率的功能. 这些功能的总体效果是让你编写的代码更简洁.更具可读性. 该语法不像许多常见做法那样繁琐. ...

随机推荐

  1. qt sql事务操作

    事务是数据库的一个重要功能,所谓事务是用户定义的一个数据库操作序列,这些操作要么全做要么全不做,是一个不可分割的工作单位.在Qt中用transaction()开始一个事务操作,用commit()函数或 ...

  2. 关于跨进程使用回调函数的研究:以跨进程获取Richedit中RTF流为例(在Delphi 初始化每一个TWinControl 对象时,将会在窗体 的属性(PropData)中加入一些标志,DLL的HInstance的值与HOST 进程的HInstance并不一致)

    建议先参考我上次写的博文跨进程获取Richedit中Text: 获得QQ聊天输入框中的内容 拿到这个问题,我习惯性地会从VCL内核开始分析.找到TRichEdit声明的单元,分析TRichEdit保存 ...

  3. 虚拟机安装 ubuntu 后,更新源无效,以及无法联网安装软件的问题

    问题: 虚拟机安装 ubuntu 后,更新源无效,以及无法联网安装软件: 错误提示: Err http://security.ubuntu.com/ubuntu/ trusty-security/un ...

  4. Windows 64 位下安装 psyco 1.6

    用 eclipse 运行 python 的时候,第一行总是有红色提示:没有安装 psyco,程序可以正常运行但是会有一点慢.于是就干脆装上吧,红色的提示还是越少越舒服. 百度了一下,在这里,http: ...

  5. 第二章 python如何运行程序

    一.python解释器介绍 Python解释器是一种让程序运行起来的程序.实际上,解释器是代码与机器的计算机硬件之间的软件逻辑层.当Python包安装在机器上后,它包含了一些最小化的组件:一个解释器和 ...

  6. select下拉箭头样式重置

    select{ appearance:none; -moz-appearance:none; -webkit-appearance:none; background: url("../ima ...

  7. PWN菜鸡入门之函数调用栈与栈溢出的联系

    一.函数调用栈过程总结 Fig 1. 函数调用发生和结束时调用栈的变化 Fig 2. 将被调用函数的参数压入栈内 Fig 3. 将被调用函数的返回地址压入栈内 Fig 4. 将调用函数的基地址(ebp ...

  8. 推荐三个学习git的网站或教程

    廖雪峰官方教程:https://www.liaoxuefeng.com/wiki/896043488029600/900388704535136 ProGit中文版:https://git-scm.c ...

  9. Spring Framework 组件注册 之 @Import

    Spring Framework 组件注册 之 @Import 写在前面 向spring中注册组件或者叫javaBean是使用spring的功能的前提条件.而且spring也提供了很多种方式,让我们可 ...

  10. 【Dubbo】Dubbo+ZK基础入门以及简单demo

    参考文档: 官方文档:http://dubbo.io/ duboo中文:https://dubbo.gitbooks.io/dubbo-user-book/content/preface/backgr ...