寻找集合中的差异

时间:2012-03-09 17:05:13

标签: c#

我有这个类(部分列表):

class CiscoSwitch 
{
  private string _SwitchName = string.Empty;
  public SwitchName {get {return _SwitchName;} set{_SwitchName=value; }}
}

我有2个CiscoSwitch对象列表。我试图比较它们来挑选那些不重复的。我只想要重复。我尝试了一个Lambda表达式,但得到了一个编译器错误,即CiscoSwitch是非delgate类型。

我现在想知道这样的事情 - 它允许我使用List.Except()方法(我认为):

static class SwitchComparer
{ 
  static bool CompareSwitchNames(CiscoSwitch s1, CiscoSwitch s2)
         {
            if (sw1.SwitchName == s2.SwitchName) {return true;}
             else {return false;}
         }
}

     // to find the differences 
 // this is a method of the CiscoSwitchClass
private List<CiscoSwitch> FindDifferences(List<CiscoSwitch> List1, List<CiscoSwitch> List2)
{
       return List1.Except(List2, SwitchComparer.CompareSwitchNames();
 }

这也可以用foreach完成,但我认为如果这是正确的话,这种方式会更清晰。我也在想有一天我可能想比较一下CiscoSwitch的其他属性,所以可以根据需要在SwitchComparer类中添加方法。

3 个答案:

答案 0 :(得分:5)

不,只是有一个像这样的方法不会帮助你。您需要实现IEqualityComparer<CiscoSwitch>以传递给Enumerable.Except - 即使这样您的代码也需要:

return List1.Except(List2, new SwitchComparer()).ToList();

Equals内覆盖GetHashCodeCiscoSwitch可以更自然地完成这一操作 - 理想情况下,您也应该实施IEquatable<CiscoSwitch>

然而,值得注意的是,像这样的可变类型对于像Dictionary<,>这样的东西玩得非常好 - 如果你以某种方式改变一个对象的方式在您将其作为键插入字典后影响其哈希码,您将无法再次获取它。如果可以,请考虑使类型不可变。

还有几点需要注意:

  • 任何时候你写:

    if (condition)
    {
        return true;
    }
    else
    {
        return false;
    }
    

    你应该写 far 更简单:

    return condition;
    

    因此,您的CompareSwitchNames方法将是:

    static bool CompareSwitchNames(CiscoSwitch s1,CiscoSwitch s2) {     return s1.SwitchName == s2.SwitchName; }

  • FindDifferences的参数名称应遵循.NET命名约定(例如list1list2

  • 使用Except只能找到第一个列表中第二个列表中没有的元素;如果您需要找到对称差异,请考虑明确使用HashSet<T>

编辑:如果你想有多种比较方式,你可以有类似的东西:

public static class SwitchComparers
{
    public static readonly IEqualityComparer<CiscoSwitch> ByName =
        new ByNameComparer();

    public static readonly IEqualityComparer<CiscoSwitch> ByCost =
        new ByCostComparer();


    private sealed class ByNameComparer : IEqualityComparer<CiscoSwitch>
    {
        // Implementation
    }

    private sealed class ByCostComparer : IEqualityComparer<CiscoSwitch>
    {
        // Implementation
    }
}

答案 1 :(得分:0)

您可以实现自定义比较器:

 public class CiscoSwitchComparer : IEqualityComparer<CiscoSwitch>
 {
   public bool Equals(CiscoSwitch x, CiscoSwitch y)
   {
       return x.SwitchName.Equals(y.SwitchName));
   }

   public int GetHashCode(CiscoSwitch obj)
   {
       return obj.SwitchName.GetHashCode();
   }
 }

然后:

private List<CiscoSwitch> FindDifferences(List<CiscoSwitch> List1, List<CiscoSwitch> List2)
{
    return List1.Concat(List2)
                .Distinct(new CiscoSwitchComparer())
                .ToList();
}

答案 2 :(得分:-1)

您应该实现IEqualityComparer[T]界面。

  

此接口允许实现自定义的相等性   收藏品的比较。也就是说,您可以创建自己的   类型T的相等定义,并指定该定义   与接受IEqualityComparer的集合类型一起使用   通用接口。在.NET Framework中,构造函数   字典泛型集合类型接受此   接口

     

默认提供此接口的默认实现   EqualityComparer泛型类的属性。 StringComparer   class实现String类型的IEqualityComparer。

     

此接口仅支持相等比较。定制   IComparer提供了排序和排序的比较   通用接口。

     

我们建议您从EqualityComparer类派生   而不是实现IEqualityComparer接口,因为   EqualityComparer类使用。来测试相等性   IEquatable.Equals方法而不是Object.Equals方法。这个   与Contains,IndexOf,LastIndexOf和Remove一致   Dictionary类和其他泛型的方法   集合。

相关问题