C#学习笔记—既有.Net接口

1、构建可枚举类型(IEnumerable和IEnumerator)

1         public IEnumerator GetEnumerator()
2 {
3 //返回数组对象的IEnumerator
4 return carArray.GetEnumerator();
5 }

2、用yield关键字构建迭代器方法

 1         public IEnumerable GetTheCars(bool ReturnRevesed)
2 {
3 //返回数组对象的IEnumerator
4 // return carArray.GetEnumerator();
5 //逆序返回项
6 if (ReturnRevesed)
7 {
8 for (int i = carArray.Length; i != 0; i--)
9 {
10 yield return carArray[i - 1];
11 }
12 }
13 else
14 {
15 //按顺序返回数组的项
16 foreach (Car c in carArray)
17 {
18 yield return c;
19 }
20 }
21 }
22
23 static void Main(string[] args)
24 {
25 Garage carLot = new Garage();
26
27 foreach (Car c in carLot)
28 {
29 Console.WriteLine("{0} is going {1} MPH", c.PetName, c.CurrentSpeed);
30 }
31 Console.WriteLine();
32
33 foreach (Car c in carLot.GetTheCars(true))
34 {
35 Console.WriteLine("{0} is going {1} MPH", c.PetName, c.CurrentSpeed);
36 }
37 Console.ReadLine();
38 }

如果自定义类型要和C#的foreach关键字一起使用的话,容器就需要定义一个名为GetEnumerator()的方法,它由IEnumerable接口类型来定制。通常,这个方法的实现只是交给保存子对象的内部成员,然而,我们也可以使用yield return语法来提供多个“命名迭代器”方法。

3、构建可克隆的对象(ICloneable)
如果给一个引用变量分配另一个引用变量,将有两个引用指向内存中的同一个对象。

 1         static void Main(string[] args)
2 {
3 //指向同一对象的两个引用
4 Point p1 = new Point(50, 50);
5 Point p2 = p1;
6 p2.X = 0;
7 Console.WriteLine(p1);
8 Console.WriteLine(p2);
9 Console.ReadLine();
10 }

如果想使自己的自定义类型支持向调用方返回自身同样副本的能力,需要实现标准ICloneable接口。

1     interface ICloneable
2 {
3 object Clone();
4 }

不同对象的Clone()方法实现不一样,但基本功能差不多,都是将成员变量的值复制到同类型的新对象实例,然后向用户返回该实例。

1         //返回一个当前对象的副本
2 public object Clone()
3 {
4 return new Point(this.X, this.Y);
5 }
 1             //请注意clone()返回了一个普通Object类型
2 //需要显式转换来获取派生类型
3 Point p3 = new Point(100, 100);
4 Point p4 = (Point)p3.Clone();
5
6 //改变p4不影响p3
7 p4.X = 0;
8
9 Console.WriteLine(p3);
10 Console.WriteLine(p4);

如果Point包含任何引用类型成员变量,MemberwiseClone()将这些引用复制到对象中(即浅复制)。如果想要真正的深复制,需要在克隆过程中创建各个引用类型变量的新实例。

 1     class Point
2 {
3 public int X { get; set; }
4 public int Y { get; set; }
5 public PointDescription desc = new PointDescription();
6
7 public Point(int xPos, int yPos, string petName) { X = xPos; Y = yPos; desc.PetName = petName; }
8 public Point(int xPos, int yPos) { X = xPos; Y = yPos; }
9
10 public Point() { }
11
12 //重写Object.ToString()
13 public override string ToString()
14 {
15 return string.Format("X = {0}; Y = {1}; Name = {2}; \nID = {3}\n", X, Y, desc.PetName, desc.PointID);
16 }
17
18 //返回一个当前对象的副本
19 public object Clone()
20 {
21 // return new Point(this.X, this.Y);
22 return this.MemberwiseClone();
23 }
 1     class PointDescription
2 {
3 public string PetName { get; set; }
4 public Guid PointID { get; set; }
5
6 public PointDescription()
7 {
8 PetName = "NO-Name";
9 PointID = Guid.NewGuid();
10 }
11 }

为使Clone()方法得到内部引用类型的深复制,需要设定由MemberwiseClone()返回的对象来表示当前点的名称。

 1         public object Clone()
2 {
3 // return new Point(this.X, this.Y);
4 // return this.MemberwiseClone();
5 //首先获取浅复制
6 Point newPoint = (Point)this.MemberwiseClone();
7
8 //然后填充间距
9 PointDescription currentDesc = new PointDescription();
10 currentDesc.PetName = this.desc.PetName;
11 newPoint.desc = currentDesc;
12 return newPoint;
13 }

概括一下克隆过程:如果有一个仅包含值类型的类或结构,使用MemberwiseClone()实现Clone()方法。如果有一个保存其他引用类型的自定义类型,需要建立一个考虑了每个引用类型成员变量的新对象。

4、构建可比较对象(IComparable)

System.Array类定义了一个名为Sort()的静态方法,在内置类型(int、short、string等)上调用这个方法的时候,可以以数字/字母顺序对数组中的项排序,因为这些内置数据类型实现了IComparable。构建自定义类型的时候,可以实现IComparable以使该类型数组可被排序,充实CompareTo()的细节时,需要决定排序操作的基准。

1         int IComparable.CompareTo(object obj)
2 {
3 Car temp = obj as Car;
4 if (temp != null)
5 return this.CarID.CompareTo(temp.CarID);
6 else
7 throw new ArgumentException("Parameter is not a car!");
8 }
 1             //建立一个Car类型数组
2 Car[] myAutos = { new Car("Rusty", 80, 1), new Car("Mary", 40, 234), new Car("Viper", 40, 34),
3 new Car("Mel", 40, 4), new Car("Chucky", 40 ,5)};
4 foreach (Car c in myAutos)
5 Console.WriteLine("{0} {1}", c.CarID, c.PetName);
6 Console.WriteLine();
7
8 Array.Sort(myAutos);
9 foreach (Car c in myAutos)
10 Console.WriteLine("{0} {1}", c.CarID, c.PetName);

5、指定多个排序顺序(IComparer)

与IComparable接口不同,IComparer接口不是在要排序的类型中,而是在许多辅助类中实现的。

 1     public class PetNameComparer : IComparer
2 {
3 int IComparer.Compare(object o1, object o2)
4 {
5 Car t1 = o1 as Car;
6 Car t2 = o2 as Car;
7 if (t1 != null && t2 != null)
8 return String.Compare(t1.PetName, t2.PetName);
9 else
10 throw new ArgumentException("Parameter is not a Car!");
11 }
12 }
1             Array.Sort(myAutos, new PetNameComparer());
2 foreach (Car c in myAutos)
3 Console.WriteLine("{0} {1}", c.CarID, c.PetName);












posted @ 2012-03-16 15:16  luffy_chen  阅读(231)  评论(0编辑  收藏  举报