集合是 OOP 中的一个重要概念, C# 中对集合的全面支持更是该语言的精华之一.
为什么要用泛型集合?
在 C# 2.0 之前, 主要可以通过两种方式实现集合:
a. 使用 ArrayList
直接将对象放入 ArrayList, 操作直观, 但由于集合中的项是 Object 类型, 因此每次使用都必须进行繁琐的类型转换.
b. 使用自定义集合类
比较常见的做法是从 CollectionBase 抽象类继承一个自定义类, 通过对 IList 对象进行封装实现强类型集合. 这种方式要求为每种集合类型写一个相应的自定义类, 工作量较大. 泛型集合的出现较好的解决了上述问题, 只需一行代码便能创建指定类型的集合.
什么是泛型?
泛型是 C# 2.0 中的新增元素 (C++ 中称为模板), 主要用于解决一系列类似的问题. 这种机制允许将类名作为参数传递给泛型类型, 并生成相应的对象. 将泛型(包括类, 接口, 方法, 委托等) 看作模板可能更好理解, 模板中的变体部分将被作为参数传进来的类名称所代替, 从而得到一个新的类型定义. 泛型是一个比较大的话题, 在此不作详细解析, 有兴趣者可以查阅相关资料.
怎样创建泛型集合?
主要利用 System.Collections.Generic 命名空间下面的 List<T > 泛型类创建集合, 语法如下:
定义 Person 类如下:
可以看到, 泛型集合大大简化了集合的实现代码, 通过它, 可以轻松创建指定类型的集合. 非但如此, 泛型集合还提供了更加强大的功能, 下面看看其中的排序及搜索.
List<T> ListOfT = new List<T>();
其中的 "T" 就是所要使用的类型, 既可以是简单类型, 如 string,int, 也可以是用户自定义类型. 下面看一个具体例子.
- class Person
- {
- private string _name; // 姓名
- private int _age; // 年龄
- // 创建 Person 对象
- public Person(string Name, int Age)
- {
- this._name= Name;
- this._age = Age;
- }
- // 姓名
- public string Name
- {
- get { return _name; }
- }
- // 年龄
- public int Age
- {
- get { return _age; }
- }
- }
- // 创建 Person 对象
- Person p1 = new Person("张三", 30);
- Person p2 = new Person("李四", 20);
- Person p3 = new Person("王五", 50);
- // 创建类型为 Person 的对象集合
- List<Person> persons = new List<Person>();
- // 将 Person 对象放入集合
- persons.Add(p1);
- persons.Add(p2);
- persons.Add(p3);
- // 输出第 2 个人的姓名
- Console.Write(persons[1].Name);
泛型集合的排序
排序基于比较, 要排序, 首先要比较. 比如有两个数 1,2, 要对他们排序, 首先就要比较这两个数, 根据比较结果来排序. 如果要比较的是对象, 情况就要复杂一点, 比如对 Person 对象进行比较, 则既可以按姓名进行比较, 也可以按年龄进行比较, 这就需要确定比较规则. 一个对象可以有多个比较规则, 但只能有一个默认规则, 默认规则放在定义该对象的类中. 默认比较规则在 CompareTo 方法中定义, 该方法属于 IComparable<T > 泛型接口. 请看下面的代码:
- class Person :IComparable<Person>
- {
- // 按年龄比较
- public int CompareTo(Person p)
- {
- return this.Age - p.Age;
- }
- }
CompareTo 方法的参数为要与之进行比较的另一个同类型对象, 返回值为 int 类型, 如果返回值大于 0, 表示第一个对象大于第二个对象, 如果返回值小于 0, 表示第一个对象小于第二个对象, 如果返回 0, 则两个对象相等.
定义好默认比较规则后, 就可以通过不带参数的 Sort 方法对集合进行排序, 如下所示:
- // 按照默认规则对集合进行排序
- persons.Sort();
- // 输出所有人姓名
- foreach (Person p in persons)
- {
- Console.WriteLine(p.Name); // 输出次序为 "李四","张三","王五"
- }
实际使用中, 经常需要对集合按照多种不同规则进行排序, 这就需要定义其他比较规则, 可以在 Compare 方法中定义, 该方法属于 IComparer<T > 泛型接口, 请看下面的代码:
- class NameComparer : IComparer<Person>
- {
- // 存放排序器实例
- public static NameComparer Default = new NameComparer();
- // 按姓名比较
- public int Compare(Person p1, Person p2)
- {
- return System.Collections.Comparer.Default.Compare(p1.Name, p2.Name);
- }
- }
Compare 方法的参数为要进行比较的两个同类型对象, 返回值为 int 类型, 返回值处理规则与 CompareTo 方法相同. 其中的 Comparer.Default 返回一个内置的 Comparer 对象, 用于比较两个同类型对象.
下面用新定义的这个比较器对集合进行排序:
还可以通过委托来进行集合排序, 首先要定义一个供委托调用的方法, 用于存放比较规则, 可以用静态方法. 请看下面的代码: 然后通过内置的泛型委托 System.Comparison<T > 对集合进行排序:
可以看到, 后两种方式都可以对集合按照指定规则进行排序, 但笔者更偏向于使用委托方式, 可以考虑把各种比较规则放在一个类中, 然后进行灵活调用.
- // 按照姓名对集合进行排序
- persons.Sort(NameComparer.Default);
- // 输出所有人姓名
- foreach (Person p in persons)
- {
- Console.WriteLine(p.Name); // 输出次序为 "李四","王五","张三"
- }
- class PersonComparison
- {
- // 按姓名比较
- public static int Name(Person p1, Person p2)
- {
- return System.Collections.Comparer.Default.Compare(p1.Name, p2.Name);
- }
- }
方法的参数为要进行比较的两个同类型对象, 返回值为 int 类型, 返回值处理规则与 CompareTo 方法相同.
- System.Comparison<Person> NameComparison = new System.Comparison<Person>(PersonComparison.Name);
- persons.Sort(NameComparison);
- // 输出所有人姓名
- foreach (Person p in persons)
- {
- Console.WriteLine(p.Name); // 输出次序为 "李四","王五","张三"
- }
可以看到, 后两种方式都可以对集合按照指定规则进行排序, 但笔者更偏向于使用委托方式, 可以考虑把各种比较规则放在一个类中, 然后进行灵活调用.
泛型集合的搜索
搜索就是从集合中找出满足特定条件的项, 可以定义多个搜索条件, 并根据需要进行调用. 首先, 定义搜索条件, 如下所示:
- class PersonPredicate
- {
- // 找出中年人(40 岁以上)
- public static bool MidAge(Person p)
- {
- if (p.Age>= 40)
- return true;
- else
- return false;
- }
- }
上面的搜索条件放在一个静态方法中, 方法的返回类型为布尔型, 集合中满足特定条件的项返回 true, 否则返回 false.
来源: http://www.bubuko.com/infodetail-2734020.html