惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
J
Java Code Geeks
雷峰网
雷峰网
WordPress大学
WordPress大学
宝玉的分享
宝玉的分享
云风的 BLOG
云风的 BLOG
V
Visual Studio Blog
V
Vulnerabilities – Threatpost
S
Securelist
The Hacker News
The Hacker News
The Register - Security
The Register - Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Help Net Security
Help Net Security
G
Google Developers Blog
Hugging Face - Blog
Hugging Face - Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
M
MIT News - Artificial intelligence
AI
AI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
The GitHub Blog
The GitHub Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Schneier on Security
Schneier on Security
N
Netflix TechBlog - Medium
T
The Blog of Author Tim Ferriss
Google DeepMind News
Google DeepMind News
Hacker News - Newest:
Hacker News - Newest: "LLM"
H
Hacker News: Front Page
博客园 - 司徒正美
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
B
Blog
Microsoft Azure Blog
Microsoft Azure Blog
大猫的无限游戏
大猫的无限游戏
Security Latest
Security Latest
Engineering at Meta
Engineering at Meta
N
News and Events Feed by Topic
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
酷 壳 – CoolShell
酷 壳 – CoolShell
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
T
Threat Research - Cisco Blogs
U
Unit 42
V
V2EX
V2EX - 技术
V2EX - 技术
L
LINUX DO - 最新话题
aimingoo的专栏
aimingoo的专栏
Microsoft Security Blog
Microsoft Security Blog
Recorded Future
Recorded Future
P
Privacy & Cybersecurity Law Blog
美团技术团队
小众软件
小众软件
F
Fortinet All Blogs

博客园 - 张少峰

在linuxdeepin10.12下源码安装bochs-2.4.6 设置pppoe时遇到“Oh, dear, I don't see the file '/etc/ppp/pppoe.conf' anywhere.”时的解决方法 安装ubuntu10.10时遇到ubi partman crashed,ubi-partman failed with exit code 141的解决方案 糗事的教训:做事一定要细心细心再细心 Reflector插件FileDisassembler汉化修改版 解压用Sixxpack2.2压缩过的程序,拿原始程序集 - 张少峰 - 博客园 利用网页挂马拿服务器的一种设想 第一次上首页,发一个玩具级的持久化工具~ python一些细微的东西 IndentationError: unindent does not match any outer indentation level Request的几种路径属性 一个方法返回多个值的解决方法 值类型与引用类型 用反射把程序集中一些泛型类实例化,怎么确定实例的类型? [转载]谓词和操作(c#版) 静态变量的继承 XPath初学笔记(四) XPath初学笔记(三) XPath初学笔记(二)
父类实现IComparable<T>接口,子类无法使用~
张少峰 · 2008-07-26 · via 博客园 - 张少峰

   这两天读了张子阳的两篇文章,基于业务对象(列表)的筛选基于业务对象(列表)的排序),如醍灌顶,大受启发。于是想在一个小网站上尝试一下。

先建立实体类,对应数据库字段,然后把数据加载到一个List<T>集合中,实现各种操作。
由于每个表都有Id这个字段,所以我写了一个抽象类;

public abstract class Entity
{
    
private int _id;

    
public int Id
    
{
        
get return _id; }
        
set { _id = value; }
    }

}

然后其他实体类继承这个抽象类:

public class User : Entity
{
    
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上实现了。

public abstract class Entity : IComparable<Entity>
{
    
private int _id;

    
public int Id
    
{
        
get return _id; }
        
set { _id = value; }
    }

    
IComparable 成员
}

接下来测试一下,为了演示,就不从数据库读数据了。

public class Test
{
    
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接口:

public abstract class Entity : IComparable
{
    
private int _id;

    
public int Id
    
{
        
get return _id; }
        
set { _id = value; }
    }


    
IComparable 成员
}

代码丑多了,而且不能保证传入的参数是不是Entity类型,看来比较之前应该还要做检查,我这里测试,就不写了。运行一下先,竟然正常了!!

更受打击了~为什么漂亮的代码不可以而丑陋的代码就行??

不行,IComparable接口的代码看着就不爽,一定有其他原因,再找找。又看了看张子阳的文章,发现他没有用继承。那就不要抽象类了,User直接实现IComparable<T>接口。

public class User :IComparable<User>
{
    
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实现了:

public abstract class Entity
{
    
private int _id;

    
public int Id
    
{
        
get return _id; }
        
set { _id = value; }
    }

}

改由User实现:

public class User : Entity, IComparable<Entity>
{
    
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 成员
}

运行一下,结果还是出错。未能比较数组中的两个元素。(就不截图了),那把类型改为子类试试:

public class User : Entity, IComparable<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 成员
}

结果正常运行~

为什么,为什么会是这样?这么搞的话我每一个实体类都要单独实现IComparable<T>接口,太麻烦了,还不如在父类里实现IComparable呢~应该有更好的方法,我是彻底晕菜了,请高手出来指点一下迷津~