引言
在开始看这本书之前看过一些技术博客,填补自己对于一些知识点的不足。无意中发现了《深入理解C#》这本书,本书主要探讨C# 2、C# 3和C# 4的细节与特性,所以做了一下阅读笔记,欢迎拍砖。
目录
- 从简单的数据类型开始
- 排序和过滤
C#1 中定义的产品类型
1 public class Product 2 { 3 string name; 4 public string Name 5 { 6 get { return name; } 7 } 8 decimal price; 9 public decimal Price10 {11 get { return price; }12 }13 public Product(string name, decimal price)14 {15 this.name = name;16 this.price = price;17 }18 public static ArrayList GetSampleProducts()19 {20 ArrayList list = new ArrayList();21 list.Add(new Product("硬装芙蓉王", 25m));22 list.Add(new Product("精白沙", 9m));23 list.Add(new Product("软白沙", 5.5m)); 25 return list;26 }27 public override string ToString()28 {29 return string.Format("{0}:{1}", name, price);30 }31 }
缺点:
- ArrayList没有提供内部有关编译时的信息。我们很有可能在GetSampleProducts方法中添加一个字符串到ArrayList中,因为ArrayList的Add方法中的参数是object,而编辑器并没有任何反应。
- 代码中提供了属性的取值方法,如果添加对应的赋值方法,那么赋值方法也必须是公共的方法。
- 创建属性的代码过于复杂。
C#2 中的强类型集合
因C#1中没有泛型,Product类中的静态方法GetSampleProducts,返回的是ArrayList类型,里面添加的元素只能是Product,而在C#2中的改变就是泛型。(新的内容用红色列出)
1 public class Product 2 { 3 string name; 4 public string Name 5 { 6 get { return name; } 7 private set { name = value; } 8 }10 decimal price;11 public decimal Price12 {13 get { return price; }14 private set { price = value; }15 }17 public Product(string name, decimal price)18 {19 Name = name;20 Price = price;21 }22 public static ListGetSampleProducts()23 {24 List list = new List ();25 list.Add(new Product("硬装芙蓉王", 25m));26 list.Add(new Product("精白沙", 9m));27 list.Add(new Product("软白沙", 5.5m));28 return list;29 }30 public override string ToString()31 {32 return string.Format("{0}:{1}", name, price);33 }34 }
优点:
- 属性有了私有赋值方法,且可以在构造函数中使用这个赋值方法。
- List<Product>告知编辑器里面只能包含Product,试图将一个不同的类型添加到列表中,会造成编译时错误。并且在使用List<Product>时不需要转换结果的数据类型。
针对C#1中的存在的局限性,C#2解决了原先存在的前两个问题。
C#3 中自动实现的属性
相对C#2而言,C#3引入了自动属性和集合初始化器。Product中的属性Name和Price,可以通过自动属性简化代码,而编译器最终生成的代码是一致的。
1 public class Product 2 { 3 public string Name{ get; private set; } 5 public decimal Price { get; private set; } 6 Product() { } 8 public Product(string name, decimal price) 9 {10 Name = name;11 Price = price;12 }14 public static ListGetSampleProducts()15 {16 return new List 17 {18 new Product("硬装芙蓉王", 25m),19 new Product("精白沙", 9m),20 new Product("软白沙", 5.5m)21 };22 }24 public override string ToString()25 {26 return string.Format("{0}:{1}", Name, Price);27 }28 }
优点:
- 没有多余的变量与属性相关联,因为类中没有了name和price变量,在类中使用属性名称是相同的。增强了代码的一致性。
- 创建的数据列表的方式也截然不同。
- 有一个私有的无参构造函数,用于新的基于属性的初始化。
C# 4 中的命名实参
在C#4中引入了命名实参,所谓命名实参是指命名参数调用实参顺序可以和形参不同。
1 public class Product 2 { 3 readonly string name; 4 public string Name 5 { 6 get { return name; } 7 } 9 readonly decimal price;10 public decimal Price11 {12 get { return price; }13 }15 public Product(string name, decimal price)16 {17 this.name = name;18 this.price = price;19 }20 public static ListGetSampleProducts()21 {22 List list = new List ();23 list.Add(new Product(name: "硬装芙蓉王", price: 25m));24 list.Add(new Product(name: "精白沙", price: 9m));25 list.Add(new Product(name: "软白沙", price: 5.5m));26 return list;27 }28 public override string ToString()29 {30 return string.Format("{0}:{1}", name, price);31 }32 }
按名称对产品进行排序
列表排序最简单的方式就是先将列表排好序,然后遍历并显示其中的项。在上述代码中,Product类中的静态方法GetSampleProducts,返回的是ArrayList类型,我们要求使用 ArrayList.Sort,要求提供一个IComparer实现。实现代码如下:
1 public class ProductNameComparer : IComparer2 {3 public int Compare(object x, object y)4 {5 Product i = (Product)x;6 Product j = (Product)y;7 return i.Name.CompareTo(j.Name);8 }9 }
1 static void Main(string[] args) 2 { 3 ArrayList arraylist = Product.GetSampleProducts(); 4 arraylist.Sort(new ProductNameComparer()); 5 foreach(Product pr in arraylist) 6 { 7 Console.WriteLine(pr.Name); 8 } 9 Console.Read();10 }
缺点:
- 必须引入额外的类型来帮助排序。
- Compare 方法中的强制类型转换。
- 假如ArrayList包含一个字符串货其他类型,那么代码会出错——因为在比较时会将字符串强制转型为 Product 。
- foreach 循环会隐式将列表中的每个元素转换为 Product 类型,如果其中包含字符串或其他类型,同样会报错。
然后在C#2中引入泛型了可以帮助我们解决上述问题。
1 public class ProductNameComparer : IComparer2 {3 public int Compare(Product x, Product y)4 {5 return x.Name.CompareTo(y.Name);6 }7 }
1 static void Main(string[] args) 2 { 3 Listarraylist = Product.GetSampleProducts(); 4 arraylist.Sort(new ProductNameComparer()); 5 foreach(Product pr in arraylist) 6 { 7 Console.WriteLine(pr.Name); 8 } 9 Console.Read();10 }
优点:
- 开始提供的就是 Product(而不可能是其他类型),在Compare方法中不需要进行强制类型转换。
- foreach也不用隐式的类型转换。
如果我们不希望引入额外的类型来帮助排序,而是直接对列表排序。C#2使用委托来排序。代码如下:
1 static void Main(string[] args) 2 { 3 Listarraylist = Product.GetSampleProducts(); 4 arraylist.Sort(delegate(Product x, Product y) 5 { 6 return x.Name.CompareTo(y.Name); 7 }); 8 foreach (Product pr in arraylist) 9 {10 Console.WriteLine(pr.Name);11 }12 13 }
C#3 可以将匿名方法替换成Lambda表达式的方式进行排序。
1 static void Main(string[] args) 2 { 3 Listarraylist = Product.GetSampleProducts(); 4 arraylist.Sort((x, y) => x.Name.CompareTo(y.Name)); 5 foreach (Product pr in arraylist) 6 { 7 Console.WriteLine(pr.Name); 8 } 9 Console.Read();10 }
C#3 使用扩展方法进行排序。
1 static void Main(string[] args)2 {3 Listarraylist = Product.GetSampleProducts();4 foreach (Product pr in arraylist.OrderBy(p => p.Name))5 {6 Console.WriteLine(pr.Name);7 }8 Console.Read();9 }
查询集合
查找集合中符合条件的所有元素,是一件很简单的事情,我们来一起来看C#1、C#2、C#之间查询集合的不同。
现要求查找价格大于20的产品信息。
C#1代码:
1 static void Main(string[] args) 2 { 3 ArrayList arraylist = Product.GetSampleProducts(); 4 foreach (Product pr in arraylist) 5 { 6 if (pr.Price > 20) 7 { 8 Console.WriteLine(pr); 9 }10 }11 Console.Read();12 }
C#2代码:
1 static void Main(string[] args) 2 { 3 Listlist = Product.GetSampleProducts(); 4 Predicate test = delegate(Product p) //设定查询条件 5 { 6 return p.Price > 20; 7 }; 8 List all = list.FindAll(test); //查询所有价格大于20的产品,并保存到all中 9 Action pro = Console.WriteLine; //输出产品信息10 all.ForEach(pro); //循环输出产品信息11 Console.Read();12 }
C#2另外一个版本代码:
1 static void Main(string[] args)2 {3 Listlist = Product.GetSampleProducts();4 list.FindAll(delegate(Product p) //设定查询条件5 {6 return p.Price > 20;7 }).ForEach(Console.WriteLine);8 Console.Read();9 }
C#3代码:
1 static void Main(string[] args)2 {3 Listlist = Product.GetSampleProducts();4 list.FindAll(p => { return p.Price > 20; }).ForEach(Console.WriteLine);5 Console.Read();6 }
1 static void Main(string[] args)2 {3 Listlist = Product.GetSampleProducts();4 foreach (Product pro in list.Where(p => p.Price > 20))5 {6 Console.WriteLine(pro);7 }8 Console.Read();9 }
这篇就写到这里。下篇我们将继续学习《深入理解C#》的相关知识。