本次讲解的是C#开发的进化史--从简单数据类型开始sass
一.C#1定义的产品类型ide
咱们将以定义一个表示产品的类型做为开始,而后进行处理。在Product类的内部,没有特别吸引人的东西,它只是封装了几个属性。还要定义在这个地方建立预约义产品的一个列表函数
代码:this
using System.Collections; public class Product { readonly string name; public string Name { get { return name; } } readonly decimal price; public decimal Price { get { return price; } } /// <summary> /// 构造函数 /// </summary> /// <param name="name"></param> /// <param name="price"></param> public Product(string name, decimal price) { this.name = name; this.price = price; } public static ArrayList GetSanpleProducts() { ArrayList list = new ArrayList(); list.Add(new Product("West Side Story ", 9.99m)); list.Add(new Product("Assassins ", 14.99m)); list.Add(new Product("Frogs ", 13.99m)); list.Add(new Product("Sweeney Todd ", 10.99m)); return list; } public override string ToString() { return string.Format("{0} {1}", name, price); } }
在这段代码中,暴露出C#1中的三个局限:spa
1.ArrayList没有提供与内部有关的编译时的信息。不慎在GetSanpleProducts建立的列表中添加一个字符串是彻底有可能的,而编译器对此没有任何反应。orm
2.代码中为属性提供了公共的取值方法,这意味着若是添加对应的赋值方法,那么赋值方法也必须是公共的。对象
3.用于建立属性和变量的代码很复杂--封装一个字符串和一个十进制数应该是一个十分简单任务,不应这么复杂。blog
2、C#2的强类型集合ci
根据C#1定义的产品类型局限,列出的前两项,在C#2进行解决。包含C#2最重要的改变:泛型。开发
强类型集合和私有的赋值方法
public class Product { string name; public string Name { get { return name; } private set { name = value; } } decimal price; public decimal Price { get { return price; } private set { price = value; } } /// <summary> /// 构造函数 /// </summary> /// <param name="name"></param> /// <param name="price"></param> public Product(string name, decimal price) { name = name; price = price; } public static List<Product> GetSanpleProducts() { List<Product> list = new List<Product>(); list.Add(new Product("West Side Story ", 9.99m)); list.Add(new Product("Assassins ", 14.99m)); list.Add(new Product("Frogs ", 13.99m)); list.Add(new Product("Sweeney Todd ", 10.99m)); return list; } public override string ToString() { return string.Format("{0} {1}", name, price); } }
属性拥有了私有的赋值方法(咱们在构造函数中使用了这两个赋值方法)。而且他能很是“聪明”地猜出List<Product>是告知编译器列表只能包含Product。试图将一个不一样的类型添加到列表中,会形成编译器时错误,而且当你从列表中获取结果时,也并不须要转换结果类型。
3、C#3中自动实现的属性
在C#2中解决了C#1的三个问题中的前两个问题,在C#3中将最后一个问题进行解决
自动实现的属性和简化的初始化,相比lambda表达式等特性来讲,有点微不足道
自动实现的属性和更简单的初始化
public class Product { public string Name { get; private set; } public decimal Price { get; private set; } /// <summary> /// 构造函数 /// </summary> /// <param name="name"></param> /// <param name="price"></param> public Product(string name, decimal price) { this.Name = name; this.Price = price; } Product() { } public static List<Product> GetSanpleProducts() { return new List<Product> { new Product("West Side Story ", 9.99m), new Product("Assassins ", 14.99m), new Product("Frogs ", 13.99m), new Product("Sweeney Todd ", 10.99m) }; } public override string ToString() { return string.Format("{0} {1}", Name, Price); } }
再也不有任何代码(或者可见的变量)与属性关联,并且硬代码的列表是以一种全然不一样的方式构建的。因为没有name和price变量可供访问,咱们必须在类中到处使用属性,这加强了一致性。如今有一个私有的无参构造函数,用于新的基于属性的初始化。(设置这些属性以前会对每一项调用这个构造函数。)
实际上能够彻底删除旧的公共构造函数。但这样依赖,外部代码就不能在建立其余的产品实例了
4、C#4中命名实参
对于C#4,涉及属性和构造函数时,咱们须要回到原始代码。其实有一个缘由是为了让它不易变:尽管拥有私有赋值方法的类型不能被公共地改变,但若是它也不能被私有的改变(面向C#1的那段代码原本也是不可变的,让它可变是为了简化面向C#2和C#3的代码段的修改),将会更加清晰。不幸的是,对只读属性,没有快捷方式。但C#4容许咱们在构造是指定实参的名称,它提供了和C#3的初始化程序同样的清晰度,并且还移除了易变性。
命名实参来了清晰的初始化代码
public class Product { readonly string name; public string Name { get { return name; } } readonly decimal price; public decimal Price { get { return price; } } readonly int supplierId; public int SupplierId { get { return supplierId; } } /// <summary> /// 构造函数 /// </summary> /// <param name="name"></param> /// <param name="price"></param> public Product(string name, decimal price,int supplierId) { this.name = name; this.price = price; this.supplierId = supplierId; } Product() { } public static List<Product> GetSanpleProducts() { return new List<Product> { new Product(name:"West Side Story ", price:9.99m,supplierId:1), new Product(name:"Assassins ", price:14.99m,supplierId:2), new Product(name:"Frogs ", price:13.99m,supplierId:3), new Product(name:"Sweeney Todd ", price:10.99m,supplierId:4) }; } public override string ToString() { return string.Format("{0} {1}", Name, Price); } }
在这个特定的示例中,该特性的好处不是很明显,但当方法或构造函数包含多个参数时,他可使代码含义更加清楚——特别是当参数类型相同,或某个参数为null时。
总结:
product类型的演变历程,展现了愈来愈好的封装性、愈来愈强类型化以及愈来愈容易的初始化
1.C#1:只读属性弱类型集合
2.C#2:私有属性赋值方法,强类型集合
3.C#3:自动实现的属性、加强的集合和对象初始化
4.C#4:用命名实参更清晰地调用构造函数和方法
到目前为止,你看到的变化幅度都不大。事实上,泛型的加入或许是C#2最重要的一部分,可是,如今只是看到了它的部分用处。