星期天 十一月 29, 2009 13:01
cSharp数组的学习笔记
这一章主要是2对接口的辨析让人纠结。不过,我们还是一对一对的来看,首先将要出场的是IEnumerable Vs IEnumerator.
IEnumerable 接口中需要实现一个GetEnumerator()方法,它返回一个IEnumerator 接口。在IEnumerator 中有MoveNext() 方法和Reset() 方法,另外还有一个current 属性。这是他们之间的关系。
值得注意的是,不论是否声明继承了接口,在指定类中实现了一个返回IEnumerator 的方法,就可以手动的通过上述的这2个方法和1个属性,进行迭代了;同样的,不论是否有显式的声明,实现了一个返回IEnumerable 的方法,就可以通过foreach 进行迭代了。下面是我推荐的一个Demo:
static void Main(string[] args)
{
testClass myTest = new testClass();
Console.WriteLine("由于在testClass 已经实现了 GetEnumerator()方法:");
//直接使用foreach来进行迭代。
foreach (string a in myTest)
{
Console.WriteLine(a);
}
//手动迭代
Console.WriteLine();
Console.WriteLine("手动迭代:");
IEnumerator enmuerator = myTest.GetEnumerator();
while (enmuerator.MoveNext())
{
Console.WriteLine(enmuerator.Current.ToString());
}
//之所以用手动迭代,是因为不能这样
//foreach (string a in enmuerator)
//{
// Console.WriteLine(a);
//}
//原因是,enmuerator不包含“GetEnumerator”的公共定义
//foreach无法发现这个定义,但IEnumerable则不同
Console.WriteLine();
Console.WriteLine("IEnumerable 还是强悍一些:");
foreach (string a in myTest.Reverse())
{
Console.WriteLine(a);
}
}
class testClass
{
string[] cars ={ "BMW Li 5", "Mercedes-benz", "Hong Qi" };
public IEnumerator GetEnumerator()
{
for (int i = 0; i < cars.Length; i++)
yield return cars[i];
}
public IEnumerable Reverse()
{
for (int i = cars.Length-1; i >= 0; i--)
{
yield return cars[i];
}
}
}
在介绍下面的接口之前,我还想补充一个有趣的继承关系:IEnumerable 是基类,接下里有ICollection 继承它,而Ilist 继承ICollection。伴随着这样的继承关系,自然地其实现的方法和属性那是越来越多的。接下来,我们该说说IComparable Vs IComparer 了.
IComparable 是为指定类型提供了CompareTo() 的方法[必须]来比较自己 .当你将指定的类声明为一个数组时,想用sort() 方法来对数组中的对象进行排序,这时如果已经实现了IComparable 则会自动调用CompareTo() 来进行比较排序。
而IComparer则是为指定类型提供了一种附加的比较机制。IComparer 附加的被实现为一个辅助比较的类,在该辅助类中提供一个Compare 方法[必须]。在指定对象的数组中,调用sort 方法时,只需传递一个该辅助类的实例,即可。由于是附加的,所以可以提供多种含有Compare 方法的辅助类,相比之下,IComparable 只能在指定类中实现一个CompareTo 的方法;从效能方面,2种方法的参数都是传递object。但不同的是,CompareTo只有一个参数。每次进行比较,Compare都需要2倍于前者的“装箱-拆箱”的操作。下面,我还是用一个Demo 来说明问题:
static void Main(string[] args)
{
mobilePhone[] mp = { new mobilePhone("Sony Ericsson",2000M),
new mobilePhone("Nokia",3000M),
new mobilePhone("Samsung",1500M),
new mobilePhone("Shan Zhai",800M),
new mobilePhone("ABC",800M),
new mobilePhone("ACC",700M)
};
//------------
Console.WriteLine("IComparable Demo:");
Array.Sort(mp);
foreach (mobilePhone m in mp)
{
Console.WriteLine(m);
}
Console.WriteLine();
//------------
Console.WriteLine("IComparer-makerASCEcomparer Demo:");
Array.Sort(mp, mobilePhone.makerASCEcomparer());
foreach (mobilePhone m in mp)
{
Console.WriteLine(m);
}
Console.WriteLine();
//------------
Console.WriteLine("IComparer-priceASCEcomparer Demo:");
Array.Sort(mp, mobilePhone.priceASCEcomparer());
foreach (mobilePhone m in mp)
{
Console.WriteLine(m);
}
Console.WriteLine();
//------------
Console.WriteLine("IComparer-priceDSCEcomparer Demo:");
Array.Sort(mp, mobilePhone.priceDSCEcomparer());
foreach (mobilePhone m in mp)
{
Console.WriteLine(m);
}
Console.WriteLine();
}
class mobilePhone:IComparable
{
private string maker;
private decimal price;
public mobilePhone(string maker,decimal price)
{
this.maker = maker;
this.price = price;
}
public string Maker
{
get
{
return maker;
}
set
{
maker = value;
}
}
public decimal Price
{
get
{
return price;
}
set
{
price = value;
}
}
int IComparable.CompareTo(object x)
{
mobilePhone other = (mobilePhone)x;
int result = this.price.CompareTo(other.price);
if (result == 0)
this.maker.CompareTo(other.maker);
return result;
}
private class priceASCE : IComparer
{
int IComparer.Compare(object x,object y)
{
mobilePhone one = (mobilePhone)x;
mobilePhone other = (mobilePhone)y;
if (one.Price > other.Price)
return 1;
else if (one.Price == other.Price)
return 0;
else
return -1;
}
}
public static IComparer priceASCEcomparer()
{
return (IComparer)new priceASCE();
}
private class priceDSCE : IComparer
{
int IComparer.Compare(object x, object y)
{
mobilePhone one = (mobilePhone)x;
mobilePhone other = (mobilePhone)y;
if (one.Price < other.Price)
return 1;
else if (one.Price == other.Price)
return 0;
else
return -1;
}
}
public static IComparer priceDSCEcomparer()
{
return (IComparer)new priceDSCE();
}
private class makerASCE : IComparer
{
int IComparer.Compare(object x, object y)
{
mobilePhone one = (mobilePhone)x;
mobilePhone other = (mobilePhone)y;
int result = one.Maker.CompareTo(other.Maker);
return result;
}
}
public static IComparer makerASCEcomparer()
{
return (IComparer)new makerASCE();
}
public override string ToString()
{
return "Mobile Made by " + Maker + ", And Its Price is " + Price.ToString("C");
}
}
其实,不得不说,不管是IComparable 还是IComparer 都能实现彼此的功能,IComparer 更符合人类排序比较的思维方式罢了。当然理性的对待问题:首先是要看对效能的需求,其次才是看个人的喜好了。
参考资料:
MSDN——How to use the IComparable and IComparer interfaces in Visual C#
- Category: csharp-note
- No Comments