Skip to main content
 首页 » 编程设计

c#之找出集合中的差异

2024年02月23日32bonelee

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

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

我有 2 个 CiscoSwitch 对象列表。我正在尝试比较它们以挑选出不重复的那些。我只想要副本。我尝试了一个 Lambda 表达式,但得到一个编译器错误,指出 CiscoSwitch 是一个非委托(delegate)类型。

我现在想知道这样的事情 - 它允许我使用 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 类添加方法。

请您参考如下方法:

不,只有一个这样的方法对您没有帮助。你需要实现一个 IEqualityComparer<CiscoSwitch>传递给 Enumerable.Except - 即便如此,您的代码也需要:

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

覆盖 Equals和 GetHashCode在 CiscoSwitch 内虽然会更自然地完成这个技巧 - 理想情况下你应该实现 IEquatable<CiscoSwitch>也是。

但是,值得注意的是像这样的可变 类型不能很好地与Dictionary<,> 之类的东西一起玩。 - 如果在将对象作为键插入字典后以影响其哈希码的方式更改对象,您将无法再次访问它。如果可以,请考虑使类型不可变。

还有几点需要注意:

  • 任何时候你写:

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

    你应该写远更简单的:

    return condition; 
    

    所以你的 CompareSwitchNames方法是:

    static bool CompareSwitchNames(CiscoSwitch s1,CiscoSwitch s2) { 返回 s1.SwitchName == s2.SwitchName;

  • FindDifferences 的参数名称应遵循 .NET 命名约定(例如 list1 和 list2 )

  • 使用 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 
    } 
}