引言

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

目录

C#1 中定义的产品类型

  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("硬装芙蓉王", 25m));
list.Add(new Product("精白沙", 9m));
list.Add(new Product("软白沙", 5.5m));
return list;
}
public override string ToString()
{
return string.Format("{0}:{1}", name, price);
}
}

缺点:

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

C#2 中的强类型集合

因C#1中没有泛型,Product类中的静态方法GetSampleProducts,返回的是ArrayList类型,里面添加的元素只能是Product,而在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; }
}
public Product(string name, decimal price)
{
Name = name;
20 Price = price;
}
public static List<Product> GetSampleProducts()
{
List<Product> list = new List<Product>();
list.Add(new Product("硬装芙蓉王", 25m));
list.Add(new Product("精白沙", 9m));
list.Add(new Product("软白沙", 5.5m));
return list;
}
public override string ToString()
{
return string.Format("{0}:{1}", name, price);
}
}

优点:

  1. 属性有了私有赋值方法,且可以在构造函数中使用这个赋值方法。
  2. List<Product>告知编辑器里面只能包含Product,试图将一个不同的类型添加到列表中,会造成编译时错误。并且在使用List<Product>时不需要转换结果的数据类型。

针对C#1中的存在的局限性,C#2解决了原先存在的前两个问题。

C#3 中自动实现的属性

相对C#2而言,C#3引入了自动属性和集合初始化器。Product中的属性Name和Price,可以通过自动属性简化代码,而编译器最终生成的代码是一致的。

 public class Product
{
public string Name{ get; private set; }
5 public decimal Price { get; private set; }
Product() { }
public Product(string name, decimal price)
{
Name = name;
Price = price;
}
public static List<Product> GetSampleProducts()
{
return new List<Product>
17 {
18 new Product("硬装芙蓉王", 25m),
19 new Product("精白沙", 9m),
20 new Product("软白沙", 5.5m)
21 };
}
public override string ToString()
{
return string.Format("{0}:{1}", Name, Price);
}
}

优点:

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

C# 4 中的命名实参

在C#4中引入了命名实参,所谓命名实参是指命名参数调用实参顺序可以和形参不同。

 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<Product> GetSampleProducts()
{
List<Product> list = new List<Product>();
list.Add(new Product(name: "硬装芙蓉王", price: 25m));
24 list.Add(new Product(name: "精白沙", price: 9m));
25 list.Add(new Product(name: "软白沙", price: 5.5m));
return list;
}
public override string ToString()
{
return string.Format("{0}:{1}", name, price);
}
}

按名称对产品进行排序

列表排序最简单的方式就是先将列表排好序,然后遍历并显示其中的项。在上述代码C# 1中,Product类中的静态方法GetSampleProducts,返回的是ArrayList类型,我们要求使用 ArrayList.Sort,要求提供一个IComparer实现。实现代码如下:

  public class ProductNameComparer : IComparer
{
public int Compare(object x, object y)
{
Product i = (Product)x;
Product j = (Product)y;
return i.Name.CompareTo(j.Name);
}
}
  static void Main(string[] args)
{
ArrayList arraylist = Product.GetSampleProducts();
arraylist.Sort(new ProductNameComparer());
foreach(Product pr in arraylist)
{
Console.WriteLine(pr.Name);
}
Console.Read();
}

缺点:

  1. 必须引入额外的类型来帮助排序。
  2. Compare 方法中的强制类型转换。
  3. 假如ArrayList包含一个字符串货其他类型,那么代码会出错——因为在比较时会将字符串强制转型为 Product 。
  4. foreach 循环会隐式将列表中的每个元素转换为 Product 类型,如果其中包含字符串或其他类型,同样会报错。

然后在C#2中引入泛型了可以帮助我们解决上述问题。

 public class ProductNameComparer : IComparer<Product>
{
public int Compare(Product x, Product y)
{
return x.Name.CompareTo(y.Name);
}
}
  static void Main(string[] args)
{
List<Product> arraylist = Product.GetSampleProducts();
arraylist.Sort(new ProductNameComparer());
foreach(Product pr in arraylist)
{
Console.WriteLine(pr.Name);
}
Console.Read();
}

优点:

  1. 开始提供的就是 Product(而不可能是其他类型),在Compare方法中不需要进行强制类型转换。
  2. foreach也不用隐式的类型转换。

如果我们不希望引入额外的类型来帮助排序,而是直接对列表排序。C#2使用委托来排序。代码如下:

 static void Main(string[] args)
{
List<Product> arraylist = Product.GetSampleProducts();
arraylist.Sort(delegate(Product x, Product y)
5 {
6 return x.Name.CompareTo(y.Name);
7 });
foreach (Product pr in arraylist)
{
Console.WriteLine(pr.Name);
}

C#3 可以将匿名方法替换成Lambda表达式的方式进行排序。

 static void Main(string[] args)
{
List<Product> arraylist = Product.GetSampleProducts();
arraylist.Sort((x, y) => x.Name.CompareTo(y.Name));
foreach (Product pr in arraylist)
{
Console.WriteLine(pr.Name);
}
Console.Read();
}

C#3 使用扩展方法进行排序。

 static void Main(string[] args)
{
List<Product> arraylist = Product.GetSampleProducts();
foreach (Product pr in arraylist.OrderBy(p => p.Name))
{
Console.WriteLine(pr.Name);
}
Console.Read();
}

查询集合

查找集合中符合条件的所有元素,是一件很简单的事情,我们来一起来看C#1、C#2、C#之间查询集合的不同。

现要求查找价格大于20的产品信息。

C#1代码:

 static void Main(string[] args)
{
ArrayList arraylist = Product.GetSampleProducts();
foreach (Product pr in arraylist)
{
if (pr.Price > )
{
Console.WriteLine(pr);
}
}
Console.Read();
}

C#2代码:

 static void Main(string[] args)
{
List<Product> list = Product.GetSampleProducts();
Predicate<Product> test = delegate(Product p) //设定查询条件
{
return p.Price > ;
};
List<Product> all = list.FindAll(test); //查询所有价格大于20的产品,并保存到all中
Action<Product> pro = Console.WriteLine; //输出产品信息
all.ForEach(pro); //循环输出产品信息
Console.Read();
}

C#2另外一个版本代码:

 static void Main(string[] args)
{
List<Product> list = Product.GetSampleProducts();
list.FindAll(delegate(Product p) //设定查询条件
5 {
6 return p.Price > 20;
7 }).ForEach(Console.WriteLine);
Console.Read();
}

C#3代码:

 static void Main(string[] args)
{
List<Product> list = Product.GetSampleProducts();
list.FindAll(p => { return p.Price > 20; }).ForEach(Console.WriteLine);
Console.Read();
}
 static void Main(string[] args)
{
List<Product> list = Product.GetSampleProducts();
foreach (Product pro in list.Where(p => p.Price > 20))
{
Console.WriteLine(pro);
}
Console.Read();
}

这篇就写到这里。下篇我们将继续学习《深入理解C#》的相关知识。

学习《深入理解C#》—— 数据类型、排序和过滤 (第一章1.1---1.2)的更多相关文章

  1. 01.C#数据类型、排序、过滤(一章1.1-1.2)

    随着看的文章及探讨越多,越发现自己实在太不定性了,看下<C#深入理解>吧,做一下读书笔记,从中发现自己的不足.闲话不说,进入正题吧. 在C#1中定下一个简单的数据类型 public cla ...

  2. 《深入理解bootstrap》读书笔记:第一章 入门准备

    一.bootstrap框架简介 Bootstrap是最流行的前端开发框架. 什么是框架:开发过程的半成品. bootstrap具有以下重要特性: (1)完整的CSS样式插件 (2)丰富的预定义样式表 ...

  3. python基础知识的学习和理解

    参考链接:https://github.com/yanhualei/about_python/tree/master/python_learning/python_base   python基础知识笔 ...

  4. Java基础系列1:深入理解Java数据类型

    Java基础系列1:深入理解Java数据类型 当初学习计算机的时候,教科书中对程序的定义是:程序=数据结构+算法,Java基础系列第一篇就聊聊Java中的数据类型. 本篇聊Java数据类型主要包括四个 ...

  5. Contoso 大学 - 3 - 排序、过滤及分页

    原文 Contoso 大学 - 3 - 排序.过滤及分页 目录 Contoso 大学 - 使用 EF Code First 创建 MVC 应用 原文地址:http://www.asp.net/mvc/ ...

  6. Compass 更智能的搜索引擎(3)--高亮,排序,过滤以及各种搜索

    要想使得一个搜索系统更加的完美,查询精确度和页面显示算是其中比较重要的两个方面.今天,我们就来谈谈怎么使得我们的搜索系统更加的完美. 关于分词 下载地址 配置 关于高亮 关于排序 原理 冗余字段 使用 ...

  7. 在Object-C中学习数据结构与算法之排序算法

    笔者在学习数据结构与算法时,尝试着将排序算法以动画的形式呈现出来更加方便理解记忆,本文配合Demo 在Object-C中学习数据结构与算法之排序算法阅读更佳. 目录 选择排序 冒泡排序 插入排序 快速 ...

  8. Typescript 学习笔记二:数据类型

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  9. 理解BSTR数据类型 神奇的BSTR

    理解BSTR数据类型 神奇的BSTR - 深蓝的日志 - 网易博客 http://blog.163.com/pugood@126/blog/static/13441759320091111115264 ...

随机推荐

  1. 一个模块包含多目录和源文件,Makefile写法

    假设这样一种情况,一个内核模块有多个目录多个源文件组成,编译成模块是Makefile如何编写呢? 我这边测试通过的一种方法介绍一下.假设该模块的组成方式如下: module--> a.c     ...

  2. 5分钟教你配置命令行界面的163邮箱client

    网易163免费邮箱相关server信息: mutt 是命令行下的邮件client,它仅是管理邮件的组织编辑,邮件的发送和接收须要调用相应的程序. 这里用的各自是getmail 和 msmtp. 过程例 ...

  3. Linux下查看磁盘挂载的三种方法

    Linux下查看磁盘挂载的三种方法 2009-06-05 23:17 好久没有更新日志了,呵呵.不是没有要写的东东.实在抽不出时间来写,要准备公司的考试呢,C++考试.已经有七个月没有写C++代码了, ...

  4. iOS-开发者相关的几种证书(转)

    分享一篇关于苹果开发者证书非常详细的解释. 哈哈,我太懒了,直接转发链接. iOS-开发者相关的几种证书

  5. 流媒体协议RTMP,RTSP与HLS有什么不同

    转载自:http://www.cuplayer.com/player/PlayerCode/Wowza/2015/0204/1774.html HLS (HTTP Live Streaming) Ap ...

  6. MySQL修改root密码的各种方法整理(转)

    整理了以下四种在MySQL中修改root密码的方法,可能对大家有所帮助! 方法1: 用SET PASSWORD命令 mysql -u root mysql> SET PASSWORD FOR ' ...

  7. ZOJ 3427 Array Slicing (scanf使用)

    题意  Watashi发明了一种蛋疼(eggache) 语言  你要为这个语言实现一个 array slicing 函数  这个函数的功能是 有一个数组初始为空  每次给你一个区间[ l, r)  和 ...

  8. WinForm下的键盘事件(KeyPress、KeyDown)及如何处理不响应键盘事件

    KeyDown事件用来处理功能键:F1 F2 F3... keyPress事件用来处理字符比如说:A B C... 1 2 3... 注:处理该事件时,需要先将窗体的 KeyPreview=true; ...

  9. 峰值因子,峰均比,Reference Level

    峰值因子(CREST Factor,CF)与 峰均比( Peak-to-Average Ratio,PAR) 对于一个波形信号,在一段时间内信号幅度峰值比上信号幅度的有效值即为信号的峰值因子,它表征了 ...

  10. servlet响应解析

    response对象可以设置一些响应信息 1)设置状态码 response.setStatus(int) 2)设置响应头信息.定时刷新或者间隔 n 秒后跳转 response.setHeader(&q ...