精通C#---接口

1.接口类型
接口是一组抽象成员的命名集合。

public interface IDbConnection : IDisposable
{
	IDbTransaction BeginTransaction();
	IDbTransaction BeginTransaction(IsolationLevel il);
	void ChangeDatabase(string databaseName);
	void Close();
	IDbCommand CreateCommand();
	void Open();

	string ConnectionString{get;set;}
	int ConnectionTimeout{get;}
	string Database{get;}
	ConnectionState State{get;}
}

接口成员总是抽象的, 每一个连接对象完全可以以自己的方式来实现这些方法。
接口只能包含抽象成员。

接口可以被任何层次结构,任何命名空间或任何程序集中的任何类或结构来实现。
可通过接口类型,来把实现了特定接口的类型当成多态处理。

public interface ICloneable
{
	object Clone();
}

class MyApp
{
	static void Main()
	{
		string mystr = "Hello";
		OperatingSystem unixOs = new OperatingSystem(PlatformID.Unix, new Version());
		System.Data.SqlClient.SqlConnection sqlCnn = new System.Data.SqlClient.SqlConnection();

		CloneMe(myStr);
		CloneMe(unixOs);
		CloneMe(sqlCnn);
	}

	private static void CloneMe(ICloneable c)
	{
		object theClone = c.Clone();// 将指向c的动态类型,对应版本的ICloneable::Clone
	}
}

2.定义自定义接口
接口不指定基类,接口可以指定基接口。
接口的成员也不指定访问修饰符【接口成员是隐式公共和抽象的】
接口是纯粹的协议,不会定义实现。
接口不能有字段,构造函数,不能提供函数实现。
接口中可以定义属性。也可以包含事件以及索引器。

接口本身仅仅是抽象成员的集合,只有被具体的类或结构实现时,才有其意义。

3.实现接口

public class Pencil : IPointy
{...}

public class SwitchBlade : object, IPointy
{...}

public class Fork : Utensil, IPointy
{...}

public struct Arrow : ICloneable, IPointy
{...}

实现接口是一个“要么全要要么全不要”的命题。

public interface IPointy
{
	byte Points{get;}
}

class Triangle : Shape, IPointy
{
	...
	public byte Points
	{
		get{return 3;}
	}
}

class Hexagon : Shape, IPointy
{
	...
	public byte Points
	{
		get{return 6;}
	}
}

4.在对象级别调用接口成员
如何动态判断一个类型支持哪些接口?
在运行时判断一个类型是否支持一个指定接口的方式
4.1.使用显式强制转换。如类型不支持被请求的接口,将收到一个无效转换异常【InvalidCastException】。
4.2.as

static void Main()
{
	Hexagon hex2 = new Hexagon("Peter");
	// 若Hexagon实现了IPointy,则返回转换后的IPointy
	// 若没实现,返回null
	IPointy itfPt2 = hex2 as IPointy;
	if(itfPts != null)
		....	
}

4.3.is

static void Main()
{
	Hexagon hex2 = new Hexagon("Peter");
	// 若Hexagon实现了IPointy,则返回true
	// 若没实现,返回false
	if(hex2 is IPointy)
		// hex2.Points
}

5.接口做参数
接口可以做参数, 任何实现了此接口的类型实例,均可以作为实参传递。
在函数内,对接口对象执行成员调用时,将调用接口对象动态类型对应的实现版本。

6.接口作为返回值

static IPointy FindFirstPointyShape(Shape[] shapes)
{
	foreach(Shape s in shapes)
	{
		if(s is IPointy)
			return s as IPointy;
	}
	return null;
}

7.接口类型数组

static void Main()
{
	IPointy[] myPointObjects = 
	{
		new Hexagon(),
		new Knife(),
		new Triangle(),
		new Fork(),
		new PitchFork()
	};

	foreach(IPointy i in myPointyObjects)
	{
		Console.WriteLine("Object has {0} points", i.Points);
	}
}

8.显式接口实现
一个类或接口可以实现多个接口,多个接口可能包含同名且参数列表一致的成员。这时要处理冲突。

public interface IDrawToForm
{
	void Draw();
}

public interface IDrawToMemory
{
	void Draw();
}

public interface IDrawToPrinter
{
	void Draw();
}

class Octagon : IDrawToForm, IDrawToMemory, IDrawToPrinter
{
	// IDrawToForm, IDrawToMemory, IDrawToPrinter接口共享同一实现
	public void Draw()
	{
		Console.WriteLine("Drawing the Octagon...");
	}
}

class OctagonEx : IDrawToForm, IDrawToMemory, IDrawToPrinter
{
	// 提供独立实现。显式实现的成员是自动私有的,不允许指定访问修饰符。
	void IDrawToForm.Draw()
	{...}
	void IDrawToMemory.Draw()
	{...}
	void IDrawToPrinter.Draw()
	{...}
}

class MyApp
{
	OctagonEx oct = new OctagonEx();
	// 对于在类中提供接口显示实现的类型,接口中显示实现的成员是私有的。
	// 要通过此类型访问接口成员的唯一方式是,先把类类型强制转换为接口类型,然后在再执行接口成员访问。
	IDrawToForm itfForm = (IDrawToForm)oct;
	itfForm.Draw();
}

#.NET基础类库中包含的许多预定义接口
1.IEnumerable,IEnumerator

public interface IEnumerable
{
	IEnumerator GetEnumerator();
}

public interface IEnumerator
{
	bool MoveNext();
	object Current{get;}
	void Reset();
}

使用示例:

using System.Collections;
public class Garage : IEnumerable
{
	private Car[] carArray = new Car[4];
	public Garage()
	{
		carArray[0] = new Car("FeeFee", 200, 0);
		carArray[1] = new Car("Clunker", 80, 0);
		carArray[2] = new Car("Zippy", 30, 0);
		carArray[3] = new Car("Fred", 30, 0);
	}

	public IEnumerator GetEnumerator()
	{
		return carArray.GetEnumerator();
	}
}

// 2,3 yield相关并不清楚
2.用yield关键字构建迭代器方法

public class Garage : IEnumerable
{
	private Car[] carArray = new Car[4];
	public IEnumerator GetEnumerator()
	{
		foreach(Car c in carArray)
		{
			// 达到yield return后,当前位置被存储下来。下次调用迭代器时会从这个位置开始执行
			yield return c;
		}
	}
}

3.构建命名迭代器

public IEnumerable GetTheCars(bool ReturnReversed)
{
	if(ReturnReversed)
	{
		for(int i = carArray.Length; i != 0; i--)
		{
			yield return carArray[i - 1];
		}
	}
	else
	{
		foreach(Car c in carArray)
		{
			yield return c;
		}
	}
}

static void Main()
{
	Garage carLot = new Garage();
	foreach(Car c in carLot)
	{
		Console.WriteLine("{0} is going {1} MPH", c.PetName, c.CurrentSpeed);
	}

	foreach(Car c in carLot.GetTheCars(true))
	{
		Console.WriteLine("{0} is going {1} MPH", c.PetName, c.CurrentSpeed);
	}

	Console.ReadLine();
}

2.ICloneable

public interface ICloneable
{
	object Clone();
}

public class Point
{
	public int X{get; set;}
	public int Y{get; set;}

	public Point(int xPos, int yPos)
	{
		X = xPos;
		Y = yPos;
	}
	public Point(){}

	public override string ToString()
	{
		return string.Format("X={0}; Y={1}", X, Y);
	}

	public object Clone()
	{
		return new Point(this.X, this.Y);
	}

	// 
	public object Clone()
	{
		// 重新在堆上分配一个类的对象,并对对象的成员变量逐个进行值拷贝。对引用类型成员变量,拷贝后新对象中引用和原对象中引用指向同一个堆上对象。
		return this.MemberwiseClone();
	}
}

static void Main(string[] args)
{
	Point p3 = new Point(100, 100);
	Point p4 = (Point)p3.Clone();
	// p4.X的改变不影响p3.X
	p4.X = 0;
}

更复杂的克隆示例

public class PointDescription
{
	public string PetName{get; set;}
	public Guid PointID{get; set;}
	public PointDescription()
	{
		PetName = "No-name";
		PointID = Guid.NewGuid();
	}
}

public class Point : ICloneable
{
	public int X{get; set;}
	public int Y{get; set;}
	public PointDescription desc = new PointDescription();
	public Point()
	{}

	public override string ToString()
	{
		return string.Format("X={0}, Y={1}, Name={2}, nID={3}\n", X,Y,desc.PetName, desc.PointID);
	}

	public object Clone()
	{
		// 分配对象,并逐个按值对对象成员进行复制。
		Point newPoint = (Point)this.MemberwiseClone();
		PointDescription currentDesc = new PointDescription();
		currentDesc.PetName = this.desc.PetName;
		newPoint.desc = currentDesc;
		return newPoint;
	}
}

3.IComparable

public interface IComparable
{
	int CompareTo(object o);
}

public class Car : IComparable
{
	...
	// < 0,A < B
	// =,A = B
	// >, A > B
	int IComparable.CompareTo(object obj)
	{
		Car temp = obj as Car;
		if(temp != null)
		{
			if(this.CarID > temp.CarID)
				return 1;
			if(this.CarID < temp.CarID)
				return -1;
			else
				return 0;
		}
		else
			throw new ArgumentException("Parameter is not a Car!");
	}
}

4.IComparer

interface IComparer
{
	int Compare(object o1, object o2);
}

public class PetNameComparer : IComparer
{
	int IComparer.Compare(object o1, object o2)
	{
		Car t1 = o1 as Car;
		Car t2 = o2 as Car;
		if(t1 != null && t2 != null)
			return String.Compare(t1.PetName, t2.PetName);
		else
			throw new ArgumentException("Parameter is not a Car!");
	}
}

class MyApp
{
	public static void Main()
	{
		Car myAuto[10];
		...
		Array.Sort(myAutos, new PetNameComparer());
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

raindayinrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值