我想比较两个集合(在C#中),但我不确定有效实现它的最佳方法.
我已经阅读了关于Enumerable.SequenceEqual的其他帖子,但这并不是我正在寻找的.
在我的情况下,如果它们都包含相同的项目(无论顺序),则两个集合将是相等的.
例:
collection1 = {1, 2, 3, 4};
collection2 = {2, 4, 1, 3};
collection1 == collection2; // true
Run Code Online (Sandbox Code Playgroud)
我通常做的是遍历一个集合中的每个项目,看看它是否存在于另一个集合中,然后循环遍历另一个集合的每个项目,看它是否存在于第一个集合中.(我首先比较长度).
if (collection1.Count != collection2.Count)
return false; // the collections are not equal
foreach (Item item in collection1)
{
if (!collection2.Contains(item))
return false; // the collections are not equal
}
foreach (Item item in collection2)
{
if (!collection1.Contains(item))
return false; // the collections are not equal
}
return true; // the collections are equal
Run Code Online (Sandbox Code Playgroud)
但是,这并不完全正确,并且它可能不是比较两个集合的最有效方法.
我能想到的一个例子是错误的:
collection1 …
Run Code Online (Sandbox Code Playgroud) 如果列表中的所有项都具有相同的值,那么我需要使用该值,否则我需要使用"otherValue".我想不出一个简单明了的做法.
我的数据库中有一些相同数字的铃声.我希望所有这些都没有重复.然后我创建了一个比较类来完成这项工作,但是函数的执行从函数中产生了很大的延迟而没有明显的,从0.6秒到3.2秒!
我做得对吗还是我必须使用其他方法?
reg.AddRange(
(from a in this.dataContext.reglements
join b in this.dataContext.Clients on a.Id_client equals b.Id
where a.date_v <= datefin && a.date_v >= datedeb
where a.Id_client == b.Id
orderby a.date_v descending
select new Class_reglement
{
nom = b.Nom,
code = b.code,
Numf = a.Numf,
})
.AsEnumerable()
.Distinct(new Compare())
.ToList());
class Compare : IEqualityComparer<Class_reglement>
{
public bool Equals(Class_reglement x, Class_reglement y)
{
if (x.Numf == y.Numf)
{
return true;
}
else { return false; }
}
public int GetHashCode(Class_reglement codeh)
{
return …
Run Code Online (Sandbox Code Playgroud) 我对这三个的理解是:
.Equals()
测试数据平等(缺乏更好的描述)..Equals()
可以为同一对象的不同实例返回True,这是最常被覆盖的方法.
.ReferenceEquals()
测试两个对象是否是同一个实例,并且不能被覆盖.
==
ReferenceEquals()
默认情况下与此相同,但可以覆盖此项.
但C#站说:
在对象类中,
Equals
和ReferenceEquals
方法在语义上是等效的,除了ReferenceEquals
它只在对象实例上有效.该ReferenceEquals
方法是静态的.
现在我没理解.任何人都可以对此有所了解吗?
我有一个包含以下两个属性的类:
public int Id { get; private set; }
public T[] Values { get; private set; }
Run Code Online (Sandbox Code Playgroud)
我做了它IEquatable<T>
并覆盖了object.Equals
这样的:
public override bool Equals(object obj)
{
return Equals(obj as SimpleTableRow<T>);
}
public bool Equals(SimpleTableRow<T> other)
{
// Check for null
if(ReferenceEquals(other, null))
return false;
// Check for same reference
if(ReferenceEquals(this, other))
return true;
// Check for same Id and same Values
return Id == other.Id && Values.SequenceEqual(other.Values);
}
Run Code Online (Sandbox Code Playgroud)
当object.Equals
我有覆盖时,我GetHashCode
当然也必须覆盖.但是我应该实现什么代码?如何从通用数组中创建哈希码?我如何将它与Id
整数相结合?
public override int …
Run Code Online (Sandbox Code Playgroud) 根据MSDN,散列函数必须具有以下属性:
如果两个对象比较相等,则每个对象的GetHashCode方法必须返回相同的值.但是,如果两个对象的比较不相等,则两个对象的GetHashCode方法不必返回不同的值.
只要没有对对象状态的修改来确定对象的Equals方法的返回值,对象的GetHashCode方法必须始终返回相同的哈希代码.请注意,这仅适用于当前应用程序的执行,并且如果再次运行应用程序,则可以返回不同的哈希代码.
为获得最佳性能,哈希函数必须为所有输入生成随机分布.
我一直在以下场景中找到自己:我创建了一个类,实现IEquatable<T>
并重写了object.Equals(object)
.MSDN声明:
重写Equals的类型也必须覆盖GetHashCode; 否则,Hashtable可能无法正常工作.
然后它通常会为我停止一点.因为,你如何正确覆盖object.GetHashCode()
?从来没有真正知道从哪里开始,这似乎是很多陷阱.
在StackOverflow中,有很多与GetHashCode重写相关的问题,但大多数问题似乎都是针对非常特殊的情况和具体问题.因此,我想在这里得到一个很好的汇编.概述与一般建议和指南.该做什么,不该做什么,常见的陷阱,从哪里开始,等等.
我希望它特别针对C#,但我认为它对其他.NET语言也有同样的作用(?).
我想也许最好的方法是每个主题创建一个答案,首先是快速简短的答案(如果可能的话,尽可能接近单行),然后可能会有更多信息,并以相关问题,讨论,博客文章等结束. ,如果有的话.然后,我可以创建一个帖子作为接受的答案(将其置于顶部),只需一个"目录".尽量保持简洁明了.而且不要只链接到其他问题和博客文章.尝试采用它们的本质,然后链接到源(特别是因为源可能会消失.另外,请尝试编辑和改进答案,而不是创建许多非常相似的答案.
我不是一个非常优秀的技术作家,但我至少会尝试格式化答案,使它们看起来很相似,创建目录等.我也会尝试在这里搜索一些相关的问题来回答部分问题.这些并且可能拉出我能管理的那些的本质.但由于我在这个主题上不是很稳定,所以我会尽量远离这个主题:p
使用C#和.NET 3.5,处理这种情况的最佳方法是什么.我有数百个字段可以从各种来源(主要是字符串)进行比较.有时,源将字符串字段返回为null,有时为空.当然,有时字段中会有文字.我当前对strA!= strB的比较并没有削减它,因为例如strA为null且strB为"".我知道我可以做string.IsNullOrEmpty导致双重比较和一些丑陋.有没有更好的方法来处理这个?我认为扩展方法,但你不能扩展运算符.
我想我正在寻找一种性感的方式来做到这一点.
我正在使用域模型,并且正在思考我们在.NET中实现这两种方法的各种方法.你最喜欢的策略是什么?
这是我目前的实施:
public override bool Equals(object obj)
{
var newObj = obj as MyClass;
if (null != newObj)
{
return this.GetHashCode() == newObj.GetHashCode();
}
else
{
return base.Equals(obj);
}
}
// Since this is an entity I can use its Id
// When I don't have an Id, I usually make a composite key of the properties
public override int GetHashCode()
{
return String.Format("MyClass{0}", this.Id.ToString()).GetHashCode();
}
Run Code Online (Sandbox Code Playgroud) 好吧,我从许多地方和消息来源得知,每当我覆盖equals()方法时,我都需要覆盖hashCode()方法.但请考虑以下代码
package test;
public class MyCustomObject {
int intVal1;
int intVal2;
public MyCustomObject(int val1, int val2){
intVal1 = val1;
intVal2 = val2;
}
public boolean equals(Object obj){
return (((MyCustomObject)obj).intVal1 == this.intVal1) &&
(((MyCustomObject)obj).intVal2 == this.intVal2);
}
public static void main(String a[]){
MyCustomObject m1 = new MyCustomObject(3,5);
MyCustomObject m2 = new MyCustomObject(3,5);
MyCustomObject m3 = new MyCustomObject(4,5);
System.out.println(m1.equals(m2));
System.out.println(m1.equals(m3));
}
}
Run Code Online (Sandbox Code Playgroud)
这里输出是真的,完全按照我想要的方式错误,我根本不关心覆盖hashCode()方法.这意味着hashCode()覆盖是一个选项而不是每个人都说的强制选项.
我想要第二次确认.
我想使用自定义对象作为Dictionary键,主要是,我有这样的事情:(我不能使用.net 4.0所以我没有元组)
class Tuple<A, B> : IEquatable<Tuple<A,B>>
{
public A AValue { get; set; }
public B BValue { get; set; }
public Tuple(A a, B b){ AValue = a; BValue = b; }
public bool Equals(Tuple<A, B> tuple)
{
return tuple.AValue.Equals(AValue) && tuple.BValue.Equals(BValue);
}
public bool Equals(object o)
{
return this.Equals(o as Tuple<A,B>);
}
}
Run Code Online (Sandbox Code Playgroud)
然后我做这样的事情.
var boolmap = new Dictionary<Tuple<bool, bool>, string>();
boolmap.Add(new Tuple<bool,bool>(true, true), "A");
boolmap.Add(new Tuple<bool,bool>(true, false), "B");
boolmap.Add(new Tuple<bool,bool>(false, true), "C");
boolmap.Add(new Tuple<bool,bool>(false, false), "D"); …
Run Code Online (Sandbox Code Playgroud) c# ×8
.net ×3
hashcode ×3
equality ×2
equals ×2
gethashcode ×2
linq ×2
arrays ×1
collections ×1
comparison ×1
generics ×1
java ×1