1.1从简单的数据类型开始
//C#1:只读属性,弱类型集合
using System.Collections;
public class Product
{
string name;
public string Name { get { return name; } }
decimal price;
public decimal Price { get { return price; } }
public Product(string name, decimal price)
{
this.name = name;
this.price = price;
}
public static ArrayList GetSampleProducts()
{
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));
list.Add("我添加了一个无关的字符串,编译器却那我没有办法!!!");
return list;
}
public override string ToString()
{
return string.Format("{0}:{1}", name, price);
}
}
}
C#1代码存在如下3个缺陷:
1.ArrayList没有提供与其内部内容有关的编译时信息。不慎在GetSampleProducts创建的列表中添加一个字符串是完全可能的,而编译器对于此没有任何反应。
2.代码中为属性提供了公共的取值方法,这意味着如果添加对应的赋值方法,那么赋值方法也必须是公共的。
3.用于创建属性和变量的代码很复杂——封装一个字符串和一个十进制数应该是一个十分简单的任务,不该这么复杂。
//C#2:私有属性赋值方法和强类型集合
using System.Collections.Generic;
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; }
}
public Product(string name, decimal price)
{
Name = name;
Price = price;
}
public static List
GetSampleProducts()
{
List
list = new List
();
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#2中解决了上面3个缺陷中的前2个。
C#2中最重要的改变:泛型。
现在,属性拥有了私有的 赋值方法(只能类内使用,这里在构造函数中使用了这两个赋值方法)。并且它能非常聪明地猜出List<Product>是告知编译器列表中只能包含Product类型的值。试图将一个不同的类型添加到列表中,编译器就会报错,并且当你从列表中获取结果时,也不需要转换结果的类型,因为取出来的一定是Product类型的值。
//C#3:自动实现的属性、增强的集合和对象初始化
using System.Collections.Generic;
public class Product
{
public string Name { get; private set; }
public decimal Price { get; private set; }
//旧的公共构造函数,可删除。(不过删除后外部代码就不能创建其他Product的实例了)
public Product(string name, decimal price)
{
Name = name;
Price = price;
}
//构造函数
Product() { }
public static List
GetSampleProducts()
{
return new List
{
new Product { Name = "West Side Story", Price = 9.99m },
new Product { Name = "Assassins", Price = 14.99m },
new Product { Name = "Frogs", Price = 13.99m },
new Product { Name = "Sweeney", Price = 10.99m }
};
}
public override string ToString()
{
return string.Format("{0}:{1}", Name, Price);
}
}
C#3解决了第3个缺陷,自动实现的属性和更简单的初始值,大大简化了代码。
现在,不再有任何代码(或者可见的变量)与属性关联,而且硬编码的列表是以一种全然不同的方式构建的。由于没有name和price变量可供访问,我们必须在类中处处使用属性,这增强了一致性。
//C#4:用命名实参更清晰地调用构造函数和方法
using System.Collections.Generic;
public class Product
{
readonly string name;
public string Name { get { return name; } }
readonly decimal price;
public decimal Price { get { return price; } }
public Product(string name, decimal price)
{
//调用构造函数时指定实参的名称
this.name = name;
this.price = price;
}
public static List
GetSampleProducts()
{
return new List
{
new Product ( name : "West Side Story", price : 9.99m ),
new Product ( name : "Assassins", price : 14.99m ),
new Product ( name : "Frogs", price : 13.99m ),
new Product ( name : "Sweeney", price : 10.99m )
};
}
public override string ToString()
{
return string.Format("{0}:{1}", name, price);
}
}
C#4移除了易变性(mutability)。
尽管私有赋值方法的类型不能被公共地改变,但如果它也不能被私有地改变,将会显得更加清晰。不幸的是,对于只读属性,没有快捷方式。但C#4允许我们在调用构造函数的时候指定实参的名称。
当方法或构造函数包含多个参数时,特别是当参数类型相同或某个参数为null时,指定实参名称可以使代码的含义更加清楚。