父类实现IComparable<T>接口,子类无法使用~
这两天读了张子阳的两篇文章,基于业务对象(列表)的筛选和基于业务对象(列表)的排序),如醍灌顶,大受启发。于是想在一个小网站上尝试一下。
先建立实体类,对应数据库字段,然后把数据加载到一个List<T>集合中,实现各种操作。
由于每个表都有Id这个字段,所以我写了一个抽象类;
{
private int _id;
public int Id
{
get { return _id; }
set { _id = value; }
}
}
然后其他实体类继承这个抽象类:
{
private string _username;
private string _password;
public string UserName
{
get { return _username; }
set { _username = value; }
}
public string PassWord
{
get { return _password; }
set { _password = value; }
}
}
先来个排序吧,看一下MSDN对List<T>排序方法的说明:
Sort() | 使用默认比较器对整个 List<T> 中的元素进行排序。 |
Sort(Comparison<T>) | 使用指定的 System.Comparison<T> 对整个 List<T> 中的元素进行排序。 |
Sort(IComparer<T>) | 使用指定的比较器对整个 List<T>) 中的元素进行排序。 |
Sort(Int32, Int32, IComparer<T>) | 使用指定的比较器对 List<T> 中某个范围内的元素进行排序。 |
先从简单的入手,使用不带参数的那个方法,实现按Id的倒序排列。按照《基于业务对象的排序》里的说法,实体类要实现 IComparable<T> 接口,于是我在Entity上实现了。
{
private int _id;
public int Id
{
get { return _id; }
set { _id = value; }
}
IComparable
}
接下来测试一下,为了演示,就不从数据库读数据了。
{
static Random rnd = new Random(Convert.ToInt32(DateTime.Now.Second));
public static void Main(string[] args)
{
List<User> lu = new List<User>();
for (int i = 0; i < 10; i++)
{
User u = new User();
u.Id = i;
u.UserName = getUserName();
u.PassWord = getPassword();
lu.Add(u);
}
lu.Sort();
lu.ForEach(delegate(User us) { Console.WriteLine("用户Id:"+us.Id+"用户名:" + us.UserName + "密码:" + us.PassWord); });
Console.Read();
}
public static string getPassword()
{
string g = Guid.NewGuid().ToString();
return g.Substring(0, g.IndexOf('-'));
}
public static string getUserName()
{
string usrchars = "1234567890";
int usrlen = 8;
string tmpstr = "";
int iRandNum;
for (int i = 0; i < usrlen; i++)
{
iRandNum = rnd.Next(usrchars.Length);
tmpstr += usrchars[iRandNum];
}
return tmpstr;
}
}
全部代码:
结果出错了。如图:
受打击了~为什么我就不行呢~
查了一下详细错误:必须至少有一个对象实现 IComparable。既然如此,那我就实现IComparable接口:
{
private int _id;
public int Id
{
get { return _id; }
set { _id = value; }
}
IComparable 成员
}
代码丑多了,而且不能保证传入的参数是不是Entity类型,看来比较之前应该还要做检查,我这里测试,就不写了。运行一下先,竟然正常了!!
更受打击了~为什么漂亮的代码不可以而丑陋的代码就行??
不行,IComparable接口的代码看着就不爽,一定有其他原因,再找找。又看了看张子阳的文章,发现他没有用继承。那就不要抽象类了,User直接实现IComparable<T>接口。
{
private string _username;
private string _password;
private int _id;
public string UserName
{
get { return _username; }
set { _username = value; }
}
public string PassWord
{
get { return _password; }
set { _password = value; }
}
public int Id
{
get { return _id; }
set { _id = value; }
}
public int CompareTo(User other)
{
return other.Id.CompareTo(this.Id);
}
}
运行一下,结果也正常!
不明白了,难道父类实现的接口在子类身上就无效了?不应该啊。赶快恢复原来的代码试一试,还让User继承Entity,Entity实现IComparable<T>接口:
结果从智能提示里可以看到,User里有CompareTo方法,应该也实现了IComparable<T>接口。难道父类实现的不行,必须自己实现,试一下,不让Entity实现了:
{
private int _id;
public int Id
{
get { return _id; }
set { _id = value; }
}
}
改由User实现:
{
private string _username;
private string _password;
public string UserName
{
get { return _username; }
set { _username = value; }
}
public string PassWord
{
get { return _password; }
set { _password = value; }
}
IComparable
}
运行一下,结果还是出错。未能比较数组中的两个元素。(就不截图了),那把类型改为子类试试:
{
private string _username;
private string _password;
public string UserName
{
get { return _username; }
set { _username = value; }
}
public string PassWord
{
get { return _password; }
set { _password = value; }
}
IComparable
}
结果正常运行~
为什么,为什么会是这样?这么搞的话我每一个实体类都要单独实现IComparable<T>接口,太麻烦了,还不如在父类里实现IComparable呢~应该有更好的方法,我是彻底晕菜了,请高手出来指点一下迷津~