关于List<T>中的Exists 和Contains的区别
2010-02-01 16:12
363 查看
转载:http://www.cnblogs.com/jicheng1014/archive/2010/02/01/1660967.html
今天在做小项目的时候,有个需求,是比较List中的对象是否存在过
而比较的对象是通过新建得来的(反序列化)
正当我使用Contains做比较的时候,
就发现问题了.
以下是测试代码
测试结果如下:
结论是,新建的一模一样的对象却在Contains中返回的false,未能通过测试
为什么会出现这种问题呢?
答案很简单:Contains比较的是存储的内存地址是否相同,而不是值相同.
我们更改下测试,就能发现问题了
结果为
很显然,当我直接从Parent中取得一个对象的时候,Contains就会抓住这个对象
那么,如果说我需要值的比较的话,怎样做到呢?
很简单,我们可以定义一个predicate委托来指定怎样进行比较:
(此处使用匿名委托代替了显式声明一个Predicate委托)
测试轻松通过
ok,委托的比较执行成功.
结论
================================
List<T>中的Contains是对对象的"内存检测",
如果想查看List<T>中是否有个对象的值跟你声明的对象的值相同
则我们需要Exists方法,且实现一个Predicate委托来指定比较的方式
================================
今天在做小项目的时候,有个需求,是比较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委托来指定比较的方式
================================
相关文章推荐
- 关于List<T>中的Exists 和Contains的区别
- List<T>中Exists 和Contains的区别
- List<T>中对比Contains, Exists, Any之间的优缺点
- List<T>中对比Contains, Exists, Any之间的优缺点
- List<T>Contains, Exists, Any之间的优缺点对比
- List<T>Find方法,FindAll方法,Contains方法,Equals方法
- wpf list<T>与ObservableCollection<T>的区别
- C#中IList<>和List<>的区别小结
- List<T> Contains方法实现
- Struts2标签——关于List<Object[]>的操作
- 关于Unchecked cast from List<String> to Iterator<String>的警告
- 关于Comparable<T>解决List<bean>,依据bean的某个属性对list进行排序
- C#中的数组、ArrayList、List<T>的区别
- C# IEnumerable<T>、IEnumerator<T>、List<T>、ArrayList、[]数组各各的区别
- 笔记1:关于List<?>和List
- Collection<String>n=new ArrayList<String>()与List<String>n=new ArrayList()的区别
- android关于序列化和反序列化List<? implement Parcelable> list属性
- 关于List<T>集合中的差集
- C++中,关于#include<***.h>和#include"***.h"的区别
- C# List<T> Contains<T>() 的用法