一、实现能够通过命名类型进行复合类型初始化的类
对象初始化器语法能够通过一种简洁的标记法来创建对象并为其字段赋值,而程序员无需为此定义不同的构造函数。
通过命名实例完成对象初始化的基本语法是,使用普通对象声明(或匿名类型声明)、new关键字以及运算符左侧的类型,另外,需要使用参数名、赋值运算符以及值,而不是圆括号和参数值。
命名实例初始化的一般语法如下:
Class variable = new Class{Property1=value1,...};
通过命名实例完成对象初始化的基本语法是,使用普通对象声明(或匿名类型声明)、new关键字以及运算符左侧的类型,另外,需要使用参数名、赋值运算符以及值,而不是圆括号和参数值。
命名实例初始化的一般语法如下:
Class variable = new Class{Property1=value1,...};
【示例】
using System;
using System.Collections.Generic;
using System.Linq;
namespace 通过命名类型初始化对象
{
class Program
{
static void Main(string[] args)
{
//Person类对象通过默认构造函数以及属性初始化过程
Person person1 = new Person();
person1.Name = "xushaui";
person1.Age = 23;
person1.Hobby = "篮球";
Console.WriteLine(person1.Name + ": " + person1.Age + "喜欢" + person1.Hobby);
//通过命名类型完成对象的初始化
Person person2 = new Person { Name = "zhuxiao", Age = 23, Hobby = "洗澡" };
Console.WriteLine(person2.Name + ": " + person2.Age + "喜欢" + person2.Hobby);
#region 使用一个查询来投影泛型list<Person>,并将投影结果存放到匿名类型names中,同时将Person类中的Name属性更名为FirstName
List<Person> person = new List<Person>
{
new Person {Name = "zhuxiao", Age = 23, Hobby = "洗澡" },
new Person {Name = "xushaui", Age = 23, Hobby = "篮球" },
new Person {Name = "xianggou", Age = 22, Hobby = "训练" }
};
//将Person类中的Name属性更名为FirstName
var names = from p in person select new { FirstName = p.Name,p.Age,p.Hobby };
foreach (var name in names)
{
Console.WriteLine(name.FirstName+":"+name.Age+"喜欢"+name.Hobby);
}
Console.ReadKey();
#endregion
}
}
}
分析:
使用命名类型方式来实例化对象比起采用构造函数实例化对象较为简洁,所编写的代码更方便,不像后者较为冗余。
使用命名类型方式来实例化对象比起采用构造函数实例化对象较为简洁,所编写的代码更方便,不像后者较为冗余。
匿名类型只能通过对象初始化器语法来初始化,因为在代码被编译之前,还没有正式被定义的类型。对匿名类型而言,对象初始化还可以用来修改属性名称,即支持属性重命名。
查询现有类型、重命名(或投影)匿名类型属性的能力被称之为整形,而得到的匿名类型则被称之为投影。
查询现有类型、重命名(或投影)匿名类型属性的能力被称之为整形,而得到的匿名类型则被称之为投影。
初始化集合解决的问题就是一次性添加所有对象,而非将一个个对象添加到这个集合中。
二、理解自动实现属性
public string Name { get; set; }
public int Age { get; set; }
public string Hobby { get; set; }
显然上述三个属性为空属性,即含有的是一个空的获取器和设置器,而编译器会自动实现该属性,即,它们就是个占位符。值得注意的是,当使用自动实现属性时,那个隐藏的私有字段只能从获取器和设置器中访问到。
自动实现属性是不允许带有标签的,因此,如若自己想要实现一个标签,就不能使用自动属性。例如,当我想实现只读的自动实现属性,则需要在set前加上private。
三、转换运算符
将数据从一种形式转换为另一种形式,常见且普遍。首先我们需要创建目标对象,然后将数据从源中复制出来,最后初始化目标对象的新实例。
3.1 ToArray
#region ToArray()示例
var numbers = new List<int>{ 1, 23, 4, 3, 54, 2, 6 };
Console.WriteLine(numbers[1]);
var arrayList = numbers.ToArray<int>();
int count = arrayList.Length;
for (int i = 0; i < count; i++)
{
Console.Write(" " + arrayList[i]);
}
#endregion
3.2 OfType
转换运算符OfType返回的是一个IEnumerable集合,该集合只含有由参数T定义的类型。
举例:在一组对象中,其中有一部分是整形,另一部分是其他类型,通过OfType我们可以快速取出我们想要的这部分对象。
举例:在一组对象中,其中有一部分是整形,另一部分是其他类型,通过OfType我们可以快速取出我们想要的这部分对象。
#region OfType<T>转换运算符快速地抽取出那些类型与参数T类型相匹配的元素
var numbers = new object[] { 1, "haahh", 2, null, "three", 2.13, '男' };
Console.WriteLine("取出numbers对象中所有整型数字:");
foreach (var itemInt in numbers.OfType<int>())
{
Console.Write(" " + itemInt);
}
#endregion
3.3 Cast
当元素不能从源类型转换为目标类型时,我们常常需要收到一个异常来了解问题的症结所在,此时可以使用Cast转换运算符。
#region 当源中的元素与T类型不一致时收到一个InvalidCastException
var numbers = new object[] { 1, "haahh", 2, null, "three", 2.13, '男' };
foreach (var itemInt in numbers.Cast<int>())
{
Console.Write(itemInt);
}
#endregion
3.4 AsEnumerable
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
const string test = "i love you littlegirl but i never never look up for you!";
MyList<string> strings = new MyList<string>();
strings.AddRange(test.Split(' '));
IEnumerable<string> inMyList = strings.Where(str => str == "never");
foreach (var s in inMyList)
{
Console.WriteLine(" {0}",s);
}
Console.ReadKey();
IEnumerable<string> notInMyList = strings.AsEnumerable().Where(str => str == "you");
foreach (var s in notInMyList)
{
Console.WriteLine(s);
}
Console.ReadLine();
}
}
public class MyList<T> : List<T>
{
public IEnumerable<T> Where(Func<T,bool> predicate)
{
Console.WriteLine("MyList");
return Enumerable.Where(this, predicate);
}
}
}
3.5 ToList
ToList转换运算符将强制进行直接查询计算,并将结果存放在一个List中。
#region 将查询结果转换为List<T>以便使我们能够向结果集添加额外的元素
var myStrings = new string[] { "hdisji", "hdsui", "dusj" };
//将查询结果转换为List<T>
List<string> stringList = (from s in myStrings select s).ToList<string>();
//向结果集添加额外的元素
stringList.Add("dgushsddfs");
stringList.Add("dgsudsidjsi");
//查询是否添加成功
Console.WriteLine("此时集合的长度:" + stringList.Count);//得到结果:5
#endregion
3.6 ToDictionary
字典是一种键值对集合。ToDictionary将一个IEnumerable对象(比如LINQ查询所返回的结果)转换为一个IDictionary对象。
#region ToDictionary示例
List<Product> products = new List<Product>
{
new Product {Code="xs1",Description="的hi是" },
new Product {Code="xs2",Description="返回数据就" },
new Product {Code="xs3",Description="哦啥的" },
new Product {Code="xs4",Description="故上帝" },
new Product {Code="xs5",Description="发货也无法hi和" }
};
//将List<T>转换为IDictionary<k,v> 存放键值对的字典
IDictionary<string, Product> dictionaryList = products.ToDictionary(key => key.Code);
Console.WriteLine(dictionaryList["xs2"].Code + " " + dictionaryList["xs2"].Description);
#endregion
分析:ToDictionary方法利用选择器Func<Product,string>来设置键。所使用的选择器Lambda表达式Key=>Key.Code,它将Code作为键并将Product对象作为值。Key是一个Product实例。
3.7 ToLookup
ToLookup用于将IEnumerable转换成Lookup类型。Lookup类似于Dictionary,只是不同的是,Dictionary每个键只对应一个值,而Lookup则将键与一组值映射起来。Lookup没有公共构造函数,而且是不可变的。在创建Lookup之后,不能添加或删除其中的元素或键。
#region ToLookup示例
//创建一个集合,存储Product对象
List<Product> products = new List<Product>
{
new Product {Code="xs1",Description="的hi是" },
new Product {Code="xs2",Description="返回数据就" },
new Product {Code="xs3",Description="哦啥的" },
new Product {Code="xs4",Description="故上帝" },
new Product {Code="xs5",Description="发货也无法hi和" }
};
//将集合转换成Lookup类型的集合
Lookup<string, string> lookup = (Lookup<string, string>)products.ToLookup(
c => c.Code.Substring(0, 2), c => c.Code + " " + c.Description);
//IGrouping:表示具有公共键的对象的集合
foreach (IGrouping<string, string> group in lookup)
{
Console.WriteLine(group.Key);
foreach (var s in group)
{
Console.WriteLine(" {0}", s);
}
}
IEnumerable<string> codeGroup = lookup["xs"];
foreach (var str in codeGroup)
{
Console.WriteLine(str);
}
#endregion