首页 > 解决方案 > 如何比较两个实现相同接口的不同类是否相等?

问题描述

public interface IMyType{
    int Val1 {get; set;}
    int Val2 {get; set;}
}


public class ImplA : IMyType{
    public int Val1 {get; set;}
    public int Val2 {get; set;}
    public string Name {get; set;}
    
}

public class ImplB : IMyType{
    public int Val1 {get; set;}
    public int Val2 {get; set;}
    public int Age {get; set;}
    
}

List<IMyType> myTypes = new List<IMyType>();
myTypes.Add(new ImplA(){ Val1 = 100, Val2 = 200, Name ="John"});
myTypes.Add(new ImplA(){ Val1 = 500, Val2 = 600, Name ="Steve"});

IMyType t = new ImplB(){ Val1 = 100, Val2 = 200, Age =30});

bool exists = myTypes.Contains(t); //returns false because types are different

它比较实现类型是否相等并导致“错误”是有道理的,但是有没有办法进行相等并包含这样它忽略实现类型而只比较接口属性是否相等?(在这个例子中它会返回真,因为 Val1 和 Val2 是相等的)

标签: c#interface

解决方案


如果你不能覆盖Equals你的类型的自定义,你总是可以为接口类型定义一个自定义的平等比较器。

using System:
using System.Collections.Generic;

// implements IEqualityComparer<IMyType> 
// it's recommended to derive from EqualityComparer<T>
public class MyTypeComparer : EqualityComparer<IMyType>
{
   public override int GetHashCode(IMyType obj){
      return HashCode.Combine(obj.Val1, obj.Val2);
      // or if System.HashCode is unavailable, something like
      // return 37 ^ obj.Val1 ^ obj.Val2;
   } 
   public override bool Equals(IMyType a, IMyType b) {
      if (ReferenceEquals(a, b)) return true;
      if (a is null || b is null) return false;
      return a.Val1 == b.Val1 && a.Val2 == b.Val2;
   } 
} 

然后使用Enumerable.Contains接受一个IEqualityComparer<T>而不是的扩展方法List<T>.Contains

using System;
using System.Linq;
using System.Collections.Generic;

var myTypes = new List<IMyType>();
myTypes.Add(new ImplA(){ Val1 = 100, Val2 = 200, Name = "John"});
myTypes.Add(new ImplA(){ Val1 = 500, Val2 = 600, Name = "Steve"});

IMyType t = new ImplB(){ Val1 = 100, Val2 = 200, Age = 30 };
bool exists = myTypes.Contains(t, new MyTypeComparer());

Console.WriteLine(exists); // true

有关示例,请参阅此SharpLab


推荐阅读