学习《深入理解C#》—— 数据类型、排序和过滤 (…

2018-06-22 07:46:07来源:未知 阅读 ()

新老客户大回馈,云服务器低至5折

引言

在开始看这本书之前看过一些技术博客,填补自己对于一些知识点的不足。无意中发现了《深入理解C#》这本书,本书主要探讨C# 2、C# 3和C# 4的细节与特性,所以做了一下阅读笔记,欢迎拍砖。

目录

  • 从简单的数据类型开始
    • C# 1 中定义的产品类型
    • 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 }

缺点:

  1. ArrayList没有提供内部有关编译时的信息。我们很有可能在GetSampleProducts方法中添加一个字符串到ArrayList中,因为ArrayList的Add方法中的参数是object,而编辑器并没有任何反应。
  2. 代码中提供了属性的取值方法,如果添加对应的赋值方法,那么赋值方法也必须是公共的方法。
  3. 创建属性的代码过于复杂。

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     }

优点:

  1. 属性有了私有赋值方法,且可以在构造函数中使用这个赋值方法。
  2. 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     }

 优点:

  1. 没有多余的变量与属性相关联,因为类中没有了name和price变量,在类中使用属性名称是相同的。增强了代码的一致性。
  2. 创建的数据列表的方式也截然不同。
  3. 有一个私有的无参构造函数,用于新的基于属性的初始化。

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         }

 缺点:

  1. 必须引入额外的类型来帮助排序。
  2. Compare 方法中的强制类型转换。
  3. 假如ArrayList包含一个字符串货其他类型,那么代码会出错——因为在比较时会将字符串强制转型为 Product 。 
  4. 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         }

 优点:

  1. 开始提供的就是 Product(而不可能是其他类型),在Compare方法中不需要进行强制类型转换。
  2. 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#》的相关知识。

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:Google Review中Zlib.Portable报错的一种排查解决方案

下一篇:asp.net 后台任务作业框架收集