C#入门经典 Part 3
Contents
CH 11
System.Collections
名空间中的几个接口提供了基本的集合功能:
IEnumerable
可以迭代集合中的项。ICollection
(继承于IEnumerable
)可以获取集合中的项的个数,并能把项复制到一个简单的数组类型中。IList
(继承于IEnumerable
和ICollection
)提供了集合的项列表,允许访问这些项,并提供其他一些与项列表的相关的基本功能。IDictionary
(继承于IEnumerable
和ICollection
)类似于IList
,但提供了可通过键值访问的项列表。
System.Array
类实现了IList
、ICollection
和IEnumerable
,表示大小固定的项列表。
System.Collections.ArrayList
类实现了IList
、ICollection
和IEnumerable
,表示大小可变的项列表。
System.Collections.CollectionBase
; System.Collections.DictionaryBase
在foreach
循环中,迭代一个collectionObject
集合的过程如下:
- 调用
collectionObject.GetEnumerator()
,返回一个IEnumerator
引用。这个方法可以通过IEnumerator
接口的实现代码来获得,但是可选。 - 调用所返回的
IEnumerator
接口的MoveNext()
方法。 - 如果
MoveNext()
方法返回true
,就使用IEnumerator
接口的Current
属性来获取对象的一个引用。 - 重复2、3直到
MoveNext()
返回false为止,此时循环停止。
迭代器: 一个代码块,顺序提供了要在foreach
循环中使用的所有值。
- 如果要迭代一个类,使用方法
GetEnumerator()
,返回类型是IEnumerator
。 - 如果要迭代一个类成员,例如一个方法,则使用
IEnumerable
。
yield
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24public static IEnumerable SimpleList()
{
yield return "a";
yield return "b";
yield return "c";
}
static void main(string[] args)
{
foreach(string str in SimpleList())
{
// ...
}
}
///
public class A
{
public IEnumerator GetEnumerator()
{
yield return ...;
}
}
浅复制和深复制1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31public class A
{
// ...
public object GetCopy()
{
return MemberwiseClone(); // 浅复制
}
}
///
public class Content
{
public int Val;
}
public class Cloner: ICloneable // 深复制
{
public Content MyContent = new Content();
public Cloner(int newVal)
{
MyContent.Val = newVal;
}
public object Clone()
{
Cloner clonedCloner = new Cloner(MyContent.Val);
return clonedCloner;
}
}
封箱 & 拆箱1
2
3A a1 = new A();
object obj = a1;
A a2 = (A)obj;
is
运算符: 检查对象是不是给定类型,或者是否可以转换为给定类型,如果是,这个运算符就返回true
。1
<operand> is <type>
运算符重载1
2
3
4
5
6
7
8
9
10
11
12
13public static A operator +(A a1, A a2) // 双目操作符
{
A ret = new A();
// ...
return ret;
}
public static A opertor -(A a) // 单目操作符
{
A ret = new A();
// ...
reutrn ret;
}
- 不要把签名相同的运算符添加到多个类中。
- 如果混合了类型,操作数的顺序必须与运算符重载的参数顺序相同。
- 不能重载赋值运算符。
- 一些运算符(如
<
和>
)必须成对重载。 - 对于
==
和!=
,通常需要重写public override bool Equals(object op1)
和public override int GetHashCode()
。
IComparable
和IComparer
接口
IComparable
在要比较的对象的类中实现,可以比较该对象和另一个对象。IComparer
在一个单独的类中实现,可以比较任意两个对象。
Comparer
: IComparer
接口的默认实现,可以对简单类型以及支持IComparable
接口的任意类型进行特定文化(不同国家语言的比较方式?)的比较,Comparer.Default.Compare(a, b)
。
对实现了IComparer
接口的类对象list进行排序1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29public class Person: IComparable
{
// ...
public int CompareTo(object obj)
{
// ...
}
}
public class PersonComparer: IComparer
{
public static PersonComparer Default = new PersonComparer();
public int Compare(object a, object b)
{
if(a is Person && b is Person)
{
return Comparer.Default.Compare(((Person)a).Name, ((Person)b).Name);
}
// ...
}
}
ArrayList list = new ArrayList();
list.Add(new Person(/* ... */));
// ...
list.Sort(); // 调用Person类中的CompareTo()方法,Person类实现了IComparable
list.Sort(PersonComparer.Default);
重载转换运算符1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public class A
{
public static implicit operator B(A a) // 隐式类型转换
{
B b = new B();
// ...
return b;
}
}
public class B
{
public static explicit operator A(B b) // 显式类型转换
{
A a = new A();
// ...
return a;
}
}
as
运算符: 把一种类型转换为指定的引用类型,如果不能转换,表达式结果为null
。1
<operand> as <type>
适用情况:
<operand>
的类型是<type>
类型;<operand>
可以隐式转换为<type>
类型;<operand>
可以封箱到<type>
类型中。