2012-04-16 4 views
1

Я использую List.Contains, чтобы определить, находится ли переменная внутри списка или нет, но она продолжает возвращаться, если это не так.Почему List.Contains не работает с моим кодом?

Я искал MSDN, и я заметил, что мне нужно наследовать от IEquatable и реализовать свой собственный метод .Equals. Фактический класс наследуется от другого, поэтому я написал метод .Equals в базовом классе.

Вот код класса «Actividad»:

abstract public class Actividad:IEquatable<Actividad> { 

    protected int codigo; 

    [...] 

    public bool Equals(Actividad otra) 
    { 
     return this.Codigo == otra.Codigo; 
    } 
} 

и вот определение класса ребенок «Actividad_a»:

public class Actividad_a : Actividad{ [...] } 

Это код, который проверяет, является ли то, что находится внутри список:

private void loadDisponibles() { 

    foreach (Actividad_a act in Program.Asignaturas) { 

     if (!user1.ActAcademicas.Contains(act)) { 
      doSomething(); 
     } 
    } 
} 

Program.Asignaturas и user1.ActAcademicas определены как List<Actividad_a>.

Проблема в том, что !user1.ActAcademicas.Contains(act) всегда возвращает true, независимо от того, находятся ли данные в списке или нет.

Мое первое предположение, что я должен наследовать от IEquatable и реализовать метод .Equals в каждом производном классе, но я не уверен в этом.

+0

ли список пуст, когда вы проверяете содержит? – asawyer

+0

Насколько я проверял, у него есть один элемент. Хотя я не проверяю, есть ли у него что-нибудь. Это имеет значение? – vguzmanp

+0

'Contains' использует' Equals', поэтому да, вы должны его реализовать. – gdoron

ответ

3

Вы сравнения Actividad_a и содержит метод ожидает, что для реализации IEquatable<Actividad_a>, а не IEquatable<Actividad>

Попробуйте заменяемое по умолчанию Равно методу, а

public override bool Equals(object otra) 
{ 
    var actividad = otra as Actividad; 
    if (actividad == null) return false; 
    return this.Codigo == actividad.Codigo; 
} 

EDIT:

Some подробнее : .NET 4.0 представила гибкость для работы с дженериками, называемыми контравариантность и ковариация http://msdn.microsoft.com/en-us/library/dd799517.aspx

Ковариантные и контравариантные параметры типового типа обеспечивают большую гибкость при назначении и использовании общих типов. Например, параметры типа ковариантного типа позволяют делать присваивания, которые выглядят , как обычный полиморфизм. Предположим, у вас есть базовый класс и производный класс с именем Base и Derived. Полиморфизм позволяет вам присваивать экземпляр Derived переменной типа Base. Точно так же, , так как параметр типа IEnumerable (Of T) интерфейс ковариантных, можно назначить экземпляр IEnumerable (IEnumerable (Of Derived) в Visual Basic) к переменному типу IEnumerable

В целом , параметр ковариантного типа может использоваться как возвращаемый тип делегата, а параметры контравариантного типа могут использоваться как типы параметров . Для интерфейса параметры ковариантного типа могут быть , используемые в качестве возвращаемых типов методов интерфейса, а контравариантные параметры типа могут использоваться в качестве типов параметров методов интерфейса .

По какой-то причине IEquatable<T>was not made contravariant и почему ваш оригинальный подход не будет работать

+1

Или, как подозревает OP, он может реализовать IEquatable на всех типах, полученных от Actividad. Однако переопределение «object.Equals» в «Actividad» - лучший подход, поэтому +1. (Кроме того, вам нужно ключевое слово override в вашем примере кода.) – phoog

+0

Это работало гладко :). Я также должен был наследовать от IEquatable vguzmanp

+0

@Fawques, вам не нужно наследовать от IEquatable , поскольку все объекты имеют метод Equals как есть. – Vadim

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