学习《深入理解C#》—— 数据类型、排序和过滤 (第一章1.1---1.2)
引言
在开始看这本书之前看过一些技术博客,填补自己对于一些知识点的不足。无意中发现了《深入理解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 Price 10 { 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 Price 12 { 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 List<Product> GetSampleProducts() 23 { 24 List<Product> list = new List<Product>(); 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 List<Product> GetSampleProducts() 15 { 16 return new List<Product> 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 Price 11 { 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 List<Product> GetSampleProducts() 21 { 22 List<Product> list = new List<Product>(); 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 }
按名称对产品进行排序
列表排序最简单的方式就是先将列表排好序,然后遍历并显示其中的项。在上述代码C# 1中,Product类中的静态方法GetSampleProducts,返回的是ArrayList类型,我们要求使用 ArrayList.Sort,要求提供一个IComparer实现。实现代码如下:
1 public class ProductNameComparer : IComparer 2 { 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 : IComparer<Product> 2 { 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 List<Product> 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 }
优点:
- 开始提供的就是 Product(而不可能是其他类型),在Compare方法中不需要进行强制类型转换。
- foreach也不用隐式的类型转换。
如果我们不希望引入额外的类型来帮助排序,而是直接对列表排序。C#2使用委托来排序。代码如下:
1 static void Main(string[] args) 2 { 3 List<Product> arraylist = 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 List<Product> arraylist = 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 List<Product> arraylist = 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 List<Product> list = Product.GetSampleProducts(); 4 Predicate<Product> test = delegate(Product p) //设定查询条件 5 { 6 return p.Price > 20; 7 }; 8 List<Product> all = list.FindAll(test); //查询所有价格大于20的产品,并保存到all中 9 Action<Product> pro = Console.WriteLine; //输出产品信息 10 all.ForEach(pro); //循环输出产品信息 11 Console.Read(); 12 }
C#2另外一个版本代码:
1 static void Main(string[] args) 2 { 3 List<Product> list = 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 List<Product> list = 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 List<Product> list = Product.GetSampleProducts(); 4 foreach (Product pro in list.Where(p => p.Price > 20)) 5 { 6 Console.WriteLine(pro); 7 } 8 Console.Read(); 9 }
这篇就写到这里。下篇我们将继续学习《深入理解C#》的相关知识。