2010-12-30 1 views
2

У меня есть несколько классов в моем приложении, все из которых имеют свойство Name, которое я хочу использовать в качестве основы для сравнения (Distinct() и т. Д.). Поскольку я всегда собираюсь сравнивать Name, я решил извлечь интерфейс, ISomeComparedStuff, который просто имеет свойство Name, которое реализуются всеми моими другими классами. Я создал класс сравнения, как, например:Linq Distinct с одним классом сравнения (и интерфейсом)

public class MyComparer : IEqualityComparer<ISomeComparedStuff> 
{ 
    public bool Equals(ISomeComparedStuff x, ISomeComparedStuff y) 
    { 
      return x.Name == y.Name; 
    } 

    public int GetHashCode(ISomeComparedStuff obj) 
    { 
      return obj.Name.GetHashCode(); 
    } 
} 

Единственная проблема, когда я пытаюсь закодировать против него:

public class SomeStuff : ISomeComparedStuff 
{ 
    ... 
} 

public class SomeMoreStuff : ISomeComparedStuff 
{ 
    ... 
} 

var someStuff = GetSomeStuff().Distinct(new MyComparer); 
var someMoreStuff = GetSomeMoreStuff().Distinct(new MyComparer); 

Я получаю ошибку произнесения (SomeStuff к ISomeComparedStuff). Есть ли способ сделать это, поэтому мне нужен только один класс сравнения, иначе мне придется создавать его для каждого из моих классов (хотя я всегда буду сравнивать на Name)?

Примечание: Я понимаю, что этот вопрос «название» нуждается в помощи. Любые предложения были бы замечательными.

ответ

2

Не уверен, что это хорошее решение или нет, но как сделать MyComparer универсальным классом?

public class MyComparer<T> : IEqualityComparer<T> 
    where T: ISomeComparedStuff 
{ 
    public bool Equals(T x, T y) 
    { 
     return x.Name == y.Name; 
    } 

    public int GetHashCode(T obj) 
    { 
     return obj.Name.GetHashCode(); 
    } 
} 

Даунсайд это вы должны новый внятную версию:

var someStuff = GetSomeStuff().Distinct(new MyComparer<SomeStuff>()); 
var someMoreStuff = GetSomeMoreStuff().Distinct(new MyComparer<SomeMoreStuff>()); 

Расширение немного, вы можете также сделать новый метод расширения, как это:

public static IEnumerable<T> DistinctByName<T>(this IEnumerable<T> values) 
    where T: ISomeComparedStuff 
{ 
    return values.Distinct(new MyComparer<T>()); 
} 
0

Может быть что-то вроде:

var someStuff = GetSomeStuff().Cast<ISomeComparedStuff>().Distinct(new MyComparer); 

Или использовать необщего IEqualityComparer.

+0

Мне нравится этот подход (особенно если он был инкапсулирован в другой метод расширения, например DistinctByName()), но вам придется отбросить элементы обратно к исходному типу, иначе получившийся «IEnumerable », вероятно, довольно бесполезен. –

+0

Да. Я был бы обеспокоен тем, что после литья я потеряю все данные. –

+0

Вы не теряете никаких данных. Отбрасывание на интерфейс не является убыточным. –

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