2012-03-09 2 views
1

У меня есть этот класс (частичный список):поиска различий в наборах

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

У меня есть 2 списков объектов CiscoSwitch. Я пытаюсь сравнить их, чтобы выбрать те, которые не дублируются. Мне нужны только дубликаты. Я попробовал выражение Lambda, но получил ошибку компилятора, что CiscoSwitch был не-дегейтным.

Я теперь интересно, о чем-то вроде этого - это позволит мне использовать метод 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(); 
} 

это также может быть сделано с Еогеасп, но я думаю, что это путь намного чище, если он правильный. Я также думаю, что есть другие атрибуты CiscoSwitch, которые, возможно, когда-нибудь захочу сравнить, так что я могу добавить методы в класс SwitchComparer, поскольку они мне нужны.

+0

Какой вопрос? – Jodrell

ответ

5

Нет, просто один такой метод не поможет. Вы должны реализовать 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) { return s1.SwitchName == s2.SwitchName; }

  • Ваши имена параметров для FindDifferences должны следовать соглашениям .NET именовании (например list1 и list2)

  • Использование Except только найти вам элементы в первом списке, которые не во втором списке; если вам нужно найти симметричную разницу, рассмотрите возможность использования HashSet<T> явно.

EDIT: Если вы хотите иметь несколько способов сравнения, вы могли бы иметь что-то вроде:

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 
    } 
} 
+0

'Except' пропустит все уникальные элементы в' List2' - насколько я могу сказать, это не то, что хочет OP – BrokenGlass

+0

@BrokenGlass: Yup, добавлял редактирование, которое включало это в конце :) –

+0

спасибо за объяснение. Является ли хорошей практикой не делать класс, который реализует IEqualityComparer static? Мое мышление заключается в том, что я мог бы сравнить другие атрибуты объекта CiscoSwitch, используя тот же статический класс, используя разные методы. Если я понимаю примеры MSDN и код, размещенный здесь, без статического класса мне понадобится один класс для каждого атрибута, который я хотел бы сравнить. –

-1

Вы должны реализовать IEqualityComparer[T] интерфейс.

Этот интерфейс позволяет реализовать индивидуальное равенство сравнение для коллекций. То есть вы можете создать собственное определение равенства для типа T и указать, что это определение должно быть , используемое с типом коллекции, который принимает общий интерфейс IEqualityComparer . В .NET Framework конструкторы типа коллекции Generic принимают этот интерфейс .

По умолчанию этот интерфейс предоставляется по умолчанию по умолчанию: свойство универсального класса EqualityComparer. Класс StringComparer реализует IEqualityComparer типа String.

Этот интерфейс поддерживает только сравнения сравнений. Настройка сопоставлений для сортировки и заказа обеспечивается общим интерфейсом IComparer .

Мы рекомендуем вам извлечь из класса EqualityComparer вместо реализации интерфейса IEqualityComparer, потому что тестов EqualityComparer класса для равенства с использованием метода IEquatable.Equals вместо метода Object.equals. Этот соответствует методам Contains, IndexOf, LastIndexOf и Remove класса Dictionary и других общих коллекций .

+0

Не за исключением. Мы не пытаемся сделать заказ, мы проверяем равенство. –

+0

I ment IEqualityComparer ... Обновленный ответ, приветствия! –

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(); 
} 
+0

Из MSDN: Мы рекомендуем, чтобы вы вышли из класса EqualityComparer вместо реализации интерфейса IEqualityComparer. –

+0

У Mhh есть какой-то источник для этого? Я не вижу ничего плохого в моей реализации, которая гарантировала бы downvote – BrokenGlass

+0

http://msdn.microsoft.com/en-us/library/ms132151.aspx –

Смежные вопросы