C# 使用标准方法(字节比较/反射)比较两个结构,即使存在Equals方法
我有一些简单的结构,它覆盖了C# 使用标准方法(字节比较/反射)比较两个结构,即使存在Equals方法,c#,reflection,struct,compare,equals,C#,Reflection,Struct,Compare,Equals,我有一些简单的结构,它覆盖了Equals()方法: 公共结构对{ 公共对(TX,TY){ X=X;Y=Y; } 公共T X{get;} 公共T{get;} 公共覆盖布尔等于(对象对象对象){ var-otherPair=(Pair)obj; 返回X.Equals(otherPair.X); } } 根据MSDN,没有Equals()方法的值类型比较如下: 如果当前实例和obj的字段都不是引用类型,那么Equals方法将对内存中的两个对象执行逐字节比较。否则,它将使用反射来比较obj和该实例的相
Equals()
方法:
公共结构对{
公共对(TX,TY){
X=X;Y=Y;
}
公共T X{get;}
公共T{get;}
公共覆盖布尔等于(对象对象对象){
var-otherPair=(Pair)obj;
返回X.Equals(otherPair.X);
}
}
根据MSDN,没有Equals()
方法的值类型比较如下:
如果当前实例和obj的字段都不是引用类型,那么Equals方法将对内存中的两个对象执行逐字节比较。否则,它将使用反射来比较obj和该实例的相应字段
我希望使用引用的方法比较Pair
s,而不是使用Pair
自己的Equals()
方法,以便以下测试通过:
[测试]
公共无效PairsEqual()
{
var p1a=新的一对(10,1);
var p1b=新的一对(10,1);
var p2=新的一对(10,2);
断言(p1a,不是等于(p2));
断言(p1a,等于(p1a));
断言(p1a,即等于(p1b));
}
这最终应该像结构的ReferenceEqual
一样工作。这可能吗?理想情况下,我希望用原始的ValueType.Equals()
方法替换比较
编辑:
我真正的愿望是能够将代码契约添加到类中,如下所示:
公共类持有者{
私人信托基金项目;
公众持有人(T项){
_项目=项目;
}
公共交通项目{
获取{return\u item;}
设置{
合同保证(_项等于(价值));
_item=value;//这可以使用反射来完成。以下解决方案基于博客文章中的代码,但代码已经缩短,专门用于ValueType.Equals()
:
这可以通过反射来实现。以下解决方案基于博客文章中的代码,但代码已经被缩短,专门用于ValueType.Equals()
:
这是一个有趣的问题,但我能问一下目的是什么吗?你想完成什么更大的任务?我有一个集合库(Sestoft的C5),其中更新(项目)
方法将使用其定义的相等比较器在集合中查找与项
相等的项,并将其替换为项
。之后,我无法使用相等比较器确保集合包含项
,因为即使它只包含旧项,也会如此。如果我有对象,使用引用等式可以很好地工作,但对于结构来说没有意义。使用“原始”Equals
但是,行为会改变。@lund.mikkel您能为您的集合类型提供一个自定义的EqualityComparer
吗?是的,但这正是我试图不使用/解决的问题。我的问题是我希望向方法添加一个代码契约,比如add(item)
对于一个列表,它确保添加的项目实际添加到列表中。想象一下,该列表已经包含示例中的p1a:如果我添加p2,列表实现可以简单地复制p1a,因为根据相等比较器,它是相等的,并且契约将错误地确认添加了项目,因为coll.Count(x=>x.Equals(item))
增加1。我不能使用coll.Count(x=>ReferenceEqual(x,item)
,因为x可能是一个结构。这是一个有趣的问题,但我能问一下目的是什么吗?你想实现什么更大的任务?我有一个集合库(Sestoft的C5),其中更新(item)
方法将使用其定义的相等比较器在集合中查找与项
相等的项,并将其替换为项
。之后,我无法使用相等比较器确保集合包含项
,因为即使它只包含旧项,也会如此。如果我有对象,使用引用等式可以很好地工作,但对于结构来说没有意义。使用“原始”Equals
但是,行为会改变。@lund.mikkel您能为您的集合类型提供一个自定义的EqualityComparer
吗?是的,但这正是我试图不使用/解决的问题。我的问题是我希望向方法添加一个代码契约,比如add(item)
对于一个列表,它确保添加的项目实际添加到列表中。想象一下,该列表已经包含示例中的p1a:如果我添加p2,列表实现可以简单地复制p1a,因为根据相等比较器,它是相等的,并且契约将错误地确认添加了项目,因为coll.Count(x=>x.Equals(item))
递增1。我不能使用coll.Count(x=>ReferenceEqual(x,item)
,因为x可能是一个结构。这似乎不适用于可移植类库。这似乎不适用于可移植类库。
public static Func<ValueType, ValueType, bool> GetValueTypeEquals()
{
var type = typeof(ValueType);
var dynamicMethod = new DynamicMethod("ValueTypeEquals", typeof(bool), new[] { type, typeof(object) }, type);
var il = dynamicMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg, 0);
il.Emit(OpCodes.Ldarg, 1);
il.EmitCall(OpCodes.Call, type.GetMethod(nameof(Equals), Public | Instance, null, new[] { type }, null), null);
il.Emit(OpCodes.Ret);
return (Func<ValueType, ValueType, bool>) dynamicMethod.CreateDelegate(typeof(Func<ValueType, ValueType, bool>));
}