C# 在泛型.Equals方法中比较两个数组
请参阅下面的代码:C# 在泛型.Equals方法中比较两个数组,c#,.net,C#,.net,请参阅下面的代码: public virtual bool Equals(T other) { if (other == null) return false; Type t = GetType(); Type otherType = other.GetType(); if (t != otherType
public virtual bool Equals(T other)
{
if (other == null)
return false;
Type t = GetType();
Type otherType = other.GetType();
if (t != otherType)
return false;
FieldInfo[] fields = t.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
foreach (FieldInfo field in fields)
{
object value1 = field.GetValue(other);
object value2 = field.GetValue(this);
if (value1 == null)
{
if (value2 != null)
return false;
}
else if (!value1.Equals(value2))
return false;
}
return true;
}
假设value1和value2是字符串数组。即使数组的内容相同,上面的代码也返回false。如果它们包含相同的内容,如何确保返回true
我看了这里,试了一下:
bool isEqual = Enumerable.SequenceEqual(value1, value2);
编译器错误是:无法从用法推断SequenceEqual。问题很可能与引用相等与值相等有关。如果比较两个不覆盖等于的对象,则比较的是它们是相同的项而不是相同的值 您看到的SequenceEqual错误与编译器不确定用于比较的类型有关。 您可以指定要用于检查相等性的类型
bool isEqual=可枚举的.SequenceEqualvalue1,value2 部分问题在于field.GetValueother返回一个对象。您可能会发现,使用递归反射来比较非类型化对象会让您感到沮丧 为了实现这一点,您必须确定字段是否为集合,如果是,则比较集合的内容。那么,如果其中一个集合包含一个集合呢?这是可行的,但令人头痛 无论您试图比较的对象是什么,如果您为要比较的类型实现或定义一个对象,则会简单得多。然后,Equals方法显式检查各个成员的相等性。如果这些成员是引用类型,则也可以为它们定义相等性。然后,如果这些类型具有更多嵌套属性,则不必深入到所有这些嵌套属性并比较它们的属性
public class Foo : IEquatable<Foo>
{
public int FooValue { get; set; }
public List<Bar> Bars { get; set; }
public bool Equals(Foo other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
if (FooValue != other.FooValue) return false;
if (Bars == null ^ other.Bars == null) return false;
return Bars == null || Bars.SequenceEqual(other.Bars);
}
}
public class Bar : IEquatable<Bar>
{
public int BarValue { get; set; }
public List<FooBar> FooBars { get; set; }
public bool Equals(Bar other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
if( BarValue != other.BarValue) return false;
if (FooBars == null ^ other.FooBars == null) return false;
return FooBars==null || FooBars.SequenceEqual(other.FooBars);
}
}
public class FooBar : IEquatable<FooBar>
{
public int FooBarValue { get; set; }
public bool Equals(FooBar other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return FooBarValue == other.FooBarValue;
}
}
这最终需要的是,您的方法知道要比较的类型,以便确切地知道如何比较它们。如果您使用反射来确定属性是什么,然后尝试检查它们是否相等,这是可能的,但这很困难,并且可能会被未来的更改破坏
下面是一个使用几个具有嵌套属性的类的示例
public class Foo : IEquatable<Foo>
{
public int FooValue { get; set; }
public List<Bar> Bars { get; set; }
public bool Equals(Foo other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
if (FooValue != other.FooValue) return false;
if (Bars == null ^ other.Bars == null) return false;
return Bars == null || Bars.SequenceEqual(other.Bars);
}
}
public class Bar : IEquatable<Bar>
{
public int BarValue { get; set; }
public List<FooBar> FooBars { get; set; }
public bool Equals(Bar other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
if( BarValue != other.BarValue) return false;
if (FooBars == null ^ other.FooBars == null) return false;
return FooBars==null || FooBars.SequenceEqual(other.FooBars);
}
}
public class FooBar : IEquatable<FooBar>
{
public int FooBarValue { get; set; }
public bool Equals(FooBar other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return FooBarValue == other.FooBarValue;
}
}
现在,当我在两个FooBar集合上使用SequenceEqual时,我会这样做:
FooBars.SequenceEqual(other.FooBars, new FooBarComparer())
这样做的另一个好处是,您可以重复使用相等比较。假设您有两个不同的类,其中有一个列。现在,这两个类都不必检查Bar及其嵌套属性来确定相等性,这将复制代码。相等性检查位于其他位置,如果需要,可以由双方共享。有关此通用相等的内容,请参见此处:@Tim Schmelter,我使用类似的方法对数据类上的复制或克隆运算符进行单元测试。请粘贴实际错误。以及产生it@pm100,我有。请看最后一行。我不能这样做,因为value1和value2是对象而不是数组。然后尝试将其预先转换,如果不可能,它将返回null:value1作为数组或更好的value1作为IEnumerableThanks+1以供IEquatable和IEqualityComparer参考。请在这里查看我问题的答案:。回答者说:让实现调用库方法。。这对我来说是可行的。你能修改你的代码吗?你可以创建一个扩展方法,比如static bool equals这个Foo foo1,Foo f2,然后把你的比较放在那里。如果有好处或需要,该类甚至可以位于另一个项目库中的方法中。其要点是,检查一个类的两个实例之间是否相等的代码不需要在类本身中。您如何知道它是一个正在传递的foo类型?您在最后一条评论中指定了foo。它可能是任何东西。谢谢。在这个例子中,扩展是基于参数的Foo。如果您想为不同的类型编写一个方法,那么您可以为该类型编写一个方法。它有更多的方法,但是为一种类型编写的方法将是准确的。尝试处理所有不同类型的相等性的方法将有问题。