您的位置:首页 > 大数据 > 人工智能

关于List<T>中的Exists 和Contains的区别

2010-02-01 16:12 363 查看
转载:http://www.cnblogs.com/jicheng1014/archive/2010/02/01/1660967.html

今天在做小项目的时候,有个需求,是比较List中的对象是否存在过

而比较的对象是通过新建得来的(反序列化)

正当我使用Contains做比较的时候,

就发现问题了.

以下是测试代码

[TestMethod()]
publicvoidRemoveDiscendantPowerTest(){
PowerParent=newPower
{
Alias="testRoot",
CanDelete=false,
Description="测试根目录",
id=100,
PowerName="测试根目录",
Childs=newList<Power>
{
newPower{
Alias="testBranch1",
CanDelete=true,
Description="枝干节点1",
id=100100,
PowerName="枝干节点1",
Childs=newList<Power>{
newPower{
Alias="leaf1",
CanDelete=true,
Description="叶子节点1",
id=100100100,
PowerName="叶子节点1"
},
newPower{
Alias="leaf2",
CanDelete=true,
Description="叶子节点2",
id=100100101,
PowerName="叶子节点2"
}
}
},
newPower{
Alias="testBranch2",
CanDelete=true,
Description="枝干节点2",
id=100101,
PowerName="枝干接点2",
Childs=newList<Power>{
newPower{
Alias="leaf3",
CanDelete=true,
Description="叶子节点3",
id=100101100,
PowerName="叶子节点3"
},
newPower{
Alias="leaf4",
CanDelete=true,
Description="叶子节点4",
id=100101101,
PowerName="叶子节点4"
}
}
}
}
};//TODO:初始化为适当的值
PowerDiscendant=newPower{
Alias="leaf4",
CanDelete=true,
Description="叶子节点4",
id=100101101,
PowerName="叶子节点4"
};
//TODO:初始化为适当的值
Assert.IsTrue(Parent.Childs[1].Childs.Contains(Discendant),"测试失败,Contains不能抓出");
}


测试结果如下:





结论是,新建的一模一样的对象却在Contains中返回的false,未能通过测试

为什么会出现这种问题呢?

答案很简单:Contains比较的是存储的内存地址是否相同,而不是值相同.

我们更改下测试,就能发现问题了

///<summary>
///RemoveDiscendantPower的测试
///</summary>
[TestMethod()]
publicvoidRemoveDiscendantPowerTest(){
PowerParent=newPower
{
Alias="testRoot",
CanDelete=false,
Description="测试根目录",
id=100,
PowerName="测试根目录",
Childs=newList<Power>
{
newPower{
Alias="testBranch1",
CanDelete=true,
Description="枝干节点1",
id=100100,
PowerName="枝干节点1",
Childs=newList<Power>{
newPower{
Alias="leaf1",
CanDelete=true,
Description="叶子节点1",
id=100100100,
PowerName="叶子节点1"
},
newPower{
Alias="leaf2",
CanDelete=true,
Description="叶子节点2",
id=100100101,
PowerName="叶子节点2"
}
}
},
newPower{
Alias="testBranch2",
CanDelete=true,
Description="枝干节点2",
id=100101,
PowerName="枝干接点2",
Childs=newList<Power>{
newPower{
Alias="leaf3",
CanDelete=true,
Description="叶子节点3",
id=100101100,
PowerName="叶子节点3"
},
newPower{
Alias="leaf4",
CanDelete=true,
Description="叶子节点4",
id=100101101,
PowerName="叶子节点4"
}
}
}
}
};//TODO:初始化为适当的值
PowerDiscendant=newPower{
Alias="leaf4",
CanDelete=true,
Description="叶子节点4",
id=100101101,
PowerName="叶子节点4"
};
//TODO:初始化为适当的值
//Assert.IsTrue(Parent.Childs[1].Childs.Contains(Discendant),"测试失败,Contains不能抓出");
Powertest=Parent.Childs[1].Childs[1];
Assert.IsTrue(Parent.Childs[1].Childs.Contains(test),"测试失败,甚至连内存引用都扯淡");
}

结果为





很显然,当我直接从Parent中取得一个对象的时候,Contains就会抓住这个对象

那么,如果说我需要值的比较的话,怎样做到呢?

很简单,我们可以定义一个predicate委托来指定怎样进行比较:

///<summary>
///RemoveDiscendantPower的测试
///</summary>
[TestMethod()]
publicvoidRemoveDiscendantPowerTest(){
PowerParent=newPower
{
Alias="testRoot",
CanDelete=false,
Description="测试根目录",
id=100,
PowerName="测试根目录",
Childs=newList<Power>
{
newPower{
Alias="testBranch1",
CanDelete=true,
Description="枝干节点1",
id=100100,
PowerName="枝干节点1",
Childs=newList<Power>{
newPower{
Alias="leaf1",
CanDelete=true,
Description="叶子节点1",
id=100100100,
PowerName="叶子节点1"
},
newPower{
Alias="leaf2",
CanDelete=true,
Description="叶子节点2",
id=100100101,
PowerName="叶子节点2"
}
}
},
newPower{
Alias="testBranch2",
CanDelete=true,
Description="枝干节点2",
id=100101,
PowerName="枝干接点2",
Childs=newList<Power>{
newPower{
Alias="leaf3",
CanDelete=true,
Description="叶子节点3",
id=100101100,
PowerName="叶子节点3"
},
newPower{
Alias="leaf4",
CanDelete=true,
Description="叶子节点4",
id=100101101,
PowerName="叶子节点4"
}
}
}
}
};//TODO:初始化为适当的值
PowerDiscendant=newPower{
Alias="leaf4",
CanDelete=true,
Description="叶子节点4",
id=100101101,
PowerName="叶子节点4"
};
//TODO:初始化为适当的值
//Assert.IsTrue(Parent.Childs[1].Childs.Contains(Discendant),"测试失败,Contains不能抓出");
//Powertest=Parent.Childs[1].Childs[1];
//Assert.IsTrue(Parent.Childs[1].Childs.Contains(test),"测试失败,甚至连内存引用都扯淡");
Assert.IsTrue(Parent.Childs[1].Childs.Exists(delegate(Powert){
returnt.id==100101101;
}));
}

(此处使用匿名委托代替了显式声明一个Predicate委托)

测试轻松通过





ok,委托的比较执行成功.

结论

================================

List<T>中的Contains是对对象的"内存检测",

如果想查看List<T>中是否有个对象的值跟你声明的对象的值相同

则我们需要Exists方法,且实现一个Predicate委托来指定比较的方式

================================
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: