前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C#3.0新增功能06 对象和集合初始值设定项

C#3.0新增功能06 对象和集合初始值设定项

作者头像
张传宁IT讲堂
发布2019-09-17 18:27:32
8890
发布2019-09-17 18:27:32
举报
文章被收录于专栏:.NET企业级解决方案应用与咨询

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

对象初始值设定项

使用对象初始值设定项,你可以在创建对象时向对象的任何可访问字段或属性分配值,而无需调用后跟赋值语句行的构造函数。 利用对象初始值设定项语法,你可为构造函数指定参数或忽略参数(以及括号语法)。 以下示例演示如何使用具有命名类型 Cat 的对象初始值设定项以及如何调用无参数构造函数。 请注意,自动实现的属性在 Cat 类中的用法。

代码语言:javascript
复制
public class Cat
{
    public int Age { get; set; }
    public string Name { get; set; }

    public Cat()
    {
    }

    public Cat(string name)
    {
        this.Name = name;
    }
}
代码语言:javascript
复制
Cat cat = new Cat { Age = 10, Name = "Fluffy" };
Cat sameCat = new Cat("Fluffy"){ Age = 10 };

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

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

代码语言:javascript
复制
public class Matrix
{
    private double[,] storage = new double[3, 3];

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

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

代码语言:javascript
复制
var identity = new Matrix
{
    [0, 0] = 1.0,
    [0, 1] = 0.0,
    [0, 2] = 0.0,

    [1, 0] = 0.0,
    [1, 1] = 1.0,
    [1, 2] = 0.0,

    [2, 0] = 0.0,
    [2, 1] = 0.0,
    [2, 2] = 1.0,
};

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

代码语言:javascript
复制
var thing = new IndexersExample {
    name = "object one",
    [1] = '1',
    [2] = '4',
    [3] = '9',
    Size = Math.PI,
    ['C',4] = "Middle C"
}

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

代码语言:javascript
复制
public string name;
public double Size { set { ... }; }
public char this[int i] { set { ... }; }
public string this[char c, int i] {  set { ... }; }

具有匿名类型的对象初始值设定项

尽管对象初始值设定项可用于任何上下文中,但它们在 LINQ 查询表达式中特别有用。 查询表达式常使用只能通过使用对象初始值设定项进行初始化的匿名类型,如下面的声明所示。

代码语言:javascript
复制
var pet = new { Age = 10, Name = "Fluffy" };

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

代码语言:javascript
复制
var productInfos =
    from p in products
    select new { p.ProductName, p.UnitPrice };

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

代码语言:javascript
复制
foreach(var p in productInfos){...}

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

代码语言:javascript
复制
select new {p.ProductName, Price = p.UnitPrice};

集合初始值设定项

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

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

代码语言:javascript
复制
List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };  
List<int> digits2 = new List<int> { 0 + 1, 12 % 3, MakeInt() };

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

代码语言:javascript
复制
List<Cat> cats = new List<Cat>
{
    new Cat{ Name = "Sylvester", Age=8 },
    new Cat{ Name = "Whiskers", Age=2 },
    new Cat{ Name = "Sasha", Age=14 }
};

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

代码语言:javascript
复制
List<Cat> moreCats = new List<Cat>
{
    new Cat{ Name = "Furrytail", Age=5 },
    new Cat{ Name = "Peaches", Age=4 },
    null
};

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

代码语言:javascript
复制
var numbers = new Dictionary<int, string>
{
    [7] = "seven",
    [9] = "nine",
    [13] = "thirteen"
};

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

代码语言:javascript
复制
var moreNumbers = new Dictionary<int, string>
{
    {19, "nineteen" },
    {23, "twenty-three" },
    {42, "forty-two" }
};

示例

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

代码语言:javascript
复制
 1 public class InitializationSample
 2 {
 3     public class Cat
 4     {
 5         // 自动属性
 6         public int Age { get; set; }
 7         public string Name { get; set; }
 8 
 9         public Cat() { }
10 
11         public Cat(string name)
12         {
13             Name = name;
14         }
15     }
16 
17     public static void Main()
18     {
19         Cat cat = new Cat { Age = 10, Name = "Fluffy" };
20         Cat sameCat = new Cat("Fluffy"){ Age = 10 };
21 
22         List<Cat> cats = new List<Cat>
23         {
24             new Cat { Name = "Sylvester", Age = 8 },
25             new Cat { Name = "Whiskers", Age = 2 },
26             new Cat { Name = "Sasha", Age = 14 }
27         };
28 
29         List<Cat> moreCats = new List<Cat>
30         {
31             new Cat { Name = "Furrytail", Age = 5 },
32             new Cat { Name = "Peaches", Age = 4 },
33             null
34         };
35 
36         // 打印结果
37         System.Console.WriteLine(cat.Name);
38 
39         foreach (Cat c in cats)
40             System.Console.WriteLine(c.Name);
41 
42         foreach (Cat c in moreCats)
43             if (c != null)
44                 System.Console.WriteLine(c.Name);
45             else
46                 System.Console.WriteLine("List element has null value.");
47     }
48     // 输出:
49     //Fluffy
50     //Sylvester
51     //Whiskers
52     //Sasha
53     //Furrytail
54     //Peaches
55     //List element has null value.
56 }

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

代码语言:javascript
复制
 1 public class FullExample
 2     { 
 3         class FormattedAddresses : IEnumerable<string>
 4         {
 5             private List<string> internalList = new List<string>();
 6             public IEnumerator<string> GetEnumerator() => internalList.GetEnumerator();
 7 
 8             System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => internalList.GetEnumerator();
 9 
10             public void Add(string firstname, string lastname, 
11                 string street, string city, 
12                 string state, string zipcode) => internalList.Add(
13                 $@"{firstname} {lastname}
14                    {street}
15                    {city}, {state} {zipcode}"
16                 );
17         }
18 
19         public static void Main()
20         {
21             FormattedAddresses addresses = new FormattedAddresses()
22             {
23                 {"John", "Doe", "123 Street", "Topeka", "KS", "00000" },
24                 {"Jane", "Smith", "456 Street", "Topeka", "KS", "00000" }
25             };
26 
27             Console.WriteLine("Address Entries:");
28 
29             foreach (string addressEntry in addresses)
30             {
31                 Console.WriteLine("\r\n" + addressEntry);
32             }
33         }
34 
35         /*
36          * 输出:
37          
38             Address Entries:
39 
40             John Doe
41             123 Street
42             Topeka, KS 00000
43 
44             Jane Smith
45             456 Street
46             Topeka, KS 00000
47          */
48     }

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

代码语言:javascript
复制
  1 public class DictionaryExample
  2 { 
  3     class RudimentaryMultiValuedDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, List<TValue>>>
  4     {
  5         private Dictionary<TKey, List<TValue>> internalDictionary = new Dictionary<TKey, List<TValue>>();
  6 
  7         public IEnumerator<KeyValuePair<TKey, List<TValue>>> GetEnumerator() => internalDictionary.GetEnumerator();
  8 
  9         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => internalDictionary.GetEnumerator();
 10 
 11         public List<TValue> this[TKey key]
 12         {
 13             get => internalDictionary[key];
 14             set => Add(key, value);
 15         }
 16 
 17         public void Add(TKey key, params TValue[] values) => Add(key, (IEnumerable<TValue>)values);
 18 
 19         public void Add(TKey key, IEnumerable<TValue> values)
 20         {
 21             if (!internalDictionary.TryGetValue(key, out List<TValue> storedValues))
 22                 internalDictionary.Add(key, storedValues = new List<TValue>());
 23 
 24             storedValues.AddRange(values);
 25         }
 26     }
 27 
 28     public static void Main()
 29     {
 30         RudimentaryMultiValuedDictionary<string, string> rudimentaryMultiValuedDictionary1
 31             = new RudimentaryMultiValuedDictionary<string, string>()
 32             {
 33                 {"Group1", "Bob", "John", "Mary" },
 34                 {"Group2", "Eric", "Emily", "Debbie", "Jesse" }
 35             };
 36         RudimentaryMultiValuedDictionary<string, string> rudimentaryMultiValuedDictionary2
 37             = new RudimentaryMultiValuedDictionary<string, string>()
 38             {
 39                 ["Group1"] = new List<string>() { "Bob", "John", "Mary" },
 40                 ["Group2"] = new List<string>() { "Eric", "Emily", "Debbie", "Jesse" }
 41             };
 42         RudimentaryMultiValuedDictionary<string, string> rudimentaryMultiValuedDictionary3
 43             = new RudimentaryMultiValuedDictionary<string, string>()
 44             {
 45                 {"Group1", new string []{ "Bob", "John", "Mary" } },
 46                 { "Group2", new string[]{ "Eric", "Emily", "Debbie", "Jesse" } }
 47             };
 48 
 49         Console.WriteLine("Using first multi-valued dictionary created with a collection initializer:");
 50 
 51         foreach (KeyValuePair<string, List<string>> group in rudimentaryMultiValuedDictionary1)
 52         {
 53             Console.WriteLine($"\r\nMembers of group {group.Key}: ");
 54 
 55             foreach (string member in group.Value)
 56             {
 57                 Console.WriteLine(member);
 58             }
 59         }
 60 
 61         Console.WriteLine("\r\nUsing second multi-valued dictionary created with a collection initializer using indexing:");
 62 
 63         foreach (KeyValuePair<string, List<string>> group in rudimentaryMultiValuedDictionary2)
 64         {
 65             Console.WriteLine($"\r\nMembers of group {group.Key}: ");
 66 
 67             foreach (string member in group.Value)
 68             {
 69                 Console.WriteLine(member);
 70             }
 71         }
 72         Console.WriteLine("\r\nUsing third multi-valued dictionary created with a collection initializer using indexing:");
 73 
 74         foreach (KeyValuePair<string, List<string>> group in rudimentaryMultiValuedDictionary3)
 75         {
 76             Console.WriteLine($"\r\nMembers of group {group.Key}: ");
 77 
 78             foreach (string member in group.Value)
 79             {
 80                 Console.WriteLine(member);
 81             }
 82         }
 83     }
 84 
 85     /*
 86      * 输出:
 87      
 88         Using first multi-valued dictionary created with a collection initializer:
 89 
 90         Members of group Group1:
 91         Bob
 92         John
 93         Mary
 94 
 95         Members of group Group2:
 96         Eric
 97         Emily
 98         Debbie
 99         Jesse
100 
101         Using second multi-valued dictionary created with a collection initializer using indexing:
102 
103         Members of group Group1:
104         Bob
105         John
106         Mary
107 
108         Members of group Group2:
109         Eric
110         Emily
111         Debbie
112         Jesse
113 
114         Using third multi-valued dictionary created with a collection initializer using indexing:
115 
116         Members of group Group1:
117         Bob
118         John
119         Mary
120 
121         Members of group Group2:
122         Eric
123         Emily
124         Debbie
125         Jesse
126      */
127 }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-07-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 示例
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档