Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用标准方法(字节比较/反射)比较两个结构,即使存在Equals方法_C#_Reflection_Struct_Compare_Equals - Fatal编程技术网

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>));
}