linq学习笔记(1):c#3.0新特性(2)
4. Object and Collection Initializers(对象和集合初始器)
Object Initializer(对象初始器),顾名思义就是一种初始化对象的方式,这个“器”并非某个具体的类或者方法。
假设我们有一个用于个人信息的数据类,如下所示:
例如,我把二个Person加到一个基于泛型的类型为Person的PersonList集合中:
然后在Person类中添加地址属性,如下:
Collection Initializer(集合初始器):就是在实例化集合类的时候采用的一种新的初始化方式。集合初始化器由一系列集合对象组成,用逗号间隔,使用{}封闭。集合初始化器可以简化把几个对象一起添加到一个集合,编译器会自动为你做集合插入操作。例如:
5. Extension Methods(扩展方法)
扩展方法是一种开发人员轻松快捷地扩展已有类型的方法定义和实现的机制。扩展方法能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。
首先,扩展方法必须是静态方法,例如下面的代码的是扩展string类型,使其拥有直接将string类型转换成decimal或int类型的方法,代码如下:
其调用方法如下:
我们很轻松地就为字符串增加了两个可能在实际项目中常常需要用到的方法,同时扩展方法还传承了C#简洁高雅的语法传统。
如上所示,扩展方法必须是静态的,因此static关键字是少不了的,扩展方法只能在非泛型或非嵌套的静态类中声明,它是通过关键字this作为其第一个参数的修饰符来声明,它的第一个参数除了this关键字以外可以没有别的修饰符,同时这个参数不能是指针类型。扩展方法具备和常规静态方法一样的能力。
扩展方法要点:
扩展方法的本质为将实例方法调用在编译期改变为静态类中的静态方法调用。事实上,它确实拥有静态方法所具有的所有功能;扩展方法的作用域是整个namespace可见的,并且可以通过using namespace来导入其它命名空间中的扩展方法;扩展方法的优先级:现有实例方法优先级最高,其次为最近的namespace下的静态类的静态方法,最后为较远的namespace下的静态类的静态方法;扩展方法是一种编译时技术,注意与反射等运行时技术进行区别,并慎重使用。
假设我们有一个用于个人信息的数据类,如下所示:
public class Person
{
public int UserID { get; set; }
public int UserAge { get; set; }
public string UserName { get; set; }
}
这个数据类只用于在内存中保存用户信息的用途,那么如果是以往,我们是这样初始化它的,首先我们可以生成一个实例,然后把各个属性值一一赋给这个实例对象,或者如果这个类的属性数量不算多,我们也可以提供一个包含所有属性的构造函数,这样我们只要在实例化的时候就可以把预先知道的属性值赋给这个对象。这是过去的老方法。下面看看C# 3.0给我们带来了新的对象初始器,那么新在哪里呢?请看下面一行代码:{
public int UserID { get; set; }
public int UserAge { get; set; }
public string UserName { get; set; }
}
Person person = new Person { UserID = 1, UserAge = 29, UserName = "peida" };
在不需要提供任何自定义构造函数的情况下,对象初始器可以让我们实现在创建类实例的时候就对它进行初始化,可以想象一下对象初始器为我们节省了多少编写自定义构造函数的工作量。对象初始化器由一系列成员对象组成,其对象必须初始化,用逗号间隔,使用{}封闭。例如,我把二个Person加到一个基于泛型的类型为Person的PersonList集合中:
IList<Person> PersonList = new List<Person>
{
new Person { UserID = 1, UserAge = 29, UserName = "peida" },
new Person { UserID = 2, UserAge = 35, UserName = "bamboo" }
};
有相同名字和类型的两个对象初始化器将会产生相同的实例,可以相互赋值,例如:{
new Person { UserID = 1, UserAge = 29, UserName = "peida" },
new Person { UserID = 2, UserAge = 35, UserName = "bamboo" }
};
Person person1 = new Person { UserID = 1, UserAge = 29, UserName = "peida" };
Person person2 = new Person { UserID = 2, UserAge = 35, UserName = "bamboo" };
person2 = person1;
除了在初始化类时设置简单的属性值外,对象初始化器特性也允许我们设置更复杂的嵌套(nested)属性类型。例如我们可以在上面定义的Person类型同时拥有一个属于Address类型的叫“Address”的属性,首先我们建一个地址类,存放个人的地址信息,如下:Person person2 = new Person { UserID = 2, UserAge = 35, UserName = "bamboo" };
person2 = person1;
public class Address
{
public string CityName { get; set; }
public string PostCode { get; set; }
}
{
public string CityName { get; set; }
public string PostCode { get; set; }
}
public class Person
{
public int UserID { get; set; }
public int UserAge { get; set; }
public string UserName { get; set; }
private Address useraddress = new Address();
public Address UserAddress
{
get { return useraddress; }
set { useraddress = value; }
}
}
接下来我们实例化Person类:{
public int UserID { get; set; }
public int UserAge { get; set; }
public string UserName { get; set; }
private Address useraddress = new Address();
public Address UserAddress
{
get { return useraddress; }
set { useraddress = value; }
}
}
Person person1 = new Person {UserID=1,UserAge=89,UserName="peida", UserAddress = { CityName = "北京", PostCode = "100001" } };
也可以这样实例化:Person person2 = new Person { UserAddress={CityName="北京",PostCode="100001"}};
这一次我们初始化时省略了其它3个属性,因为对象初始器并不要求开发人员如果使用它就必须一次性对所有属性进行初始化。Collection Initializer(集合初始器):就是在实例化集合类的时候采用的一种新的初始化方式。集合初始化器由一系列集合对象组成,用逗号间隔,使用{}封闭。集合初始化器可以简化把几个对象一起添加到一个集合,编译器会自动为你做集合插入操作。例如:
List<string> WeekDay = new List<string> { "周日", "周一", "周二", "周三", "周四", "周五", "周六" };
对象与集合初始化器要点:对象初始化器实际上利用了编译器对对象中对外可见的字段和属性进行按序赋值。;对象初始化器允许只给一部分属性赋值,包括internal访问级别;对象初始化器可以结合构造函数一起使用,并且构造函数初始化先于对象初始化器执行;集合初始化器会对初始化器中的元素进行按序调用ICollection<T>.Add(T)方法;注意对象初始化器和集合初始化器中成员的可见性和调用顺序;对象与集合初始化器同样是一种编译时技术。5. Extension Methods(扩展方法)
扩展方法是一种开发人员轻松快捷地扩展已有类型的方法定义和实现的机制。扩展方法能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。
首先,扩展方法必须是静态方法,例如下面的代码的是扩展string类型,使其拥有直接将string类型转换成decimal或int类型的方法,代码如下:
public static class ExtensionMethod
{
public static decimal ToMoney(this string money)
{
decimal number = 0m;
if (!decimal.TryParse(money, out number))
{
throw new ArgumentException("Money Error Information.");
}
return number;
}
public static int ToAge(this string age)
{
int number = 0;
if (!int.TryParse(age, out number))
{
throw new ArgumentException("Age Error Information.");
}
return number;
}
}
{
public static decimal ToMoney(this string money)
{
decimal number = 0m;
if (!decimal.TryParse(money, out number))
{
throw new ArgumentException("Money Error Information.");
}
return number;
}
public static int ToAge(this string age)
{
int number = 0;
if (!int.TryParse(age, out number))
{
throw new ArgumentException("Age Error Information.");
}
return number;
}
}
string strInpurtMoney = Console.ReadLine();
decimal UserMoney = strInpurtMoney.ToMoney();
string strInpurtAge = Console.ReadLine();
int UserAge = strInpurtAge.ToAge();
decimal UserMoney = strInpurtMoney.ToMoney();
string strInpurtAge = Console.ReadLine();
int UserAge = strInpurtAge.ToAge();
如上所示,扩展方法必须是静态的,因此static关键字是少不了的,扩展方法只能在非泛型或非嵌套的静态类中声明,它是通过关键字this作为其第一个参数的修饰符来声明,它的第一个参数除了this关键字以外可以没有别的修饰符,同时这个参数不能是指针类型。扩展方法具备和常规静态方法一样的能力。
扩展方法要点:
扩展方法的本质为将实例方法调用在编译期改变为静态类中的静态方法调用。事实上,它确实拥有静态方法所具有的所有功能;扩展方法的作用域是整个namespace可见的,并且可以通过using namespace来导入其它命名空间中的扩展方法;扩展方法的优先级:现有实例方法优先级最高,其次为最近的namespace下的静态类的静态方法,最后为较远的namespace下的静态类的静态方法;扩展方法是一种编译时技术,注意与反射等运行时技术进行区别,并慎重使用。