C # Реализация IEquatable <T>.Equal <T> - PullRequest
5 голосов
/ 17 января 2010

У меня есть такой класс:

public class Foo<T> : IEquatable<T> where T : struct
{
    List<T> lst;
    [Other irrelevant member stuff]
}

Я хочу реализовать интерфейс IEquatable<T> для класса Foo. Что мне нужно делать. Для простоты я хочу просто проверить, равны ли члены списка.

Спасибо.

C # 4.0 поддерживаемые ответы допустимы.

Обновление: вот что у меня сейчас:

public bool Equals(Foo<T> foo)
{
    return lst.Equals(foo.lst);
}

public override bool Equals(Object obj)
{
    if (obj == null) return base.Equals(obj);

    if (!(obj is Foo<T>))
    {
        throw new Exception("The 'obj' argument is not a Foo<T> object.");
    }
    else
    {
            return Equals(obj as Foo<T>)
    }
}    

public override int GetHashCode()
{
    return this.lst.GetHashCode();
}

public static bool operator ==(Foo<T> f1, Foo<T> f2)
{
   return f1.Equals(f2);
}

public static bool operator !=(Foo<T> f1, Foo<T> f2)
{
   return (!f1.Equals(f2));
}

Я получаю эту ошибку:

Error 1 'Foo<T>' does not implement interface member 'System.IEquatable<T>.Equals(T)

Ответы [ 2 ]

12 голосов
/ 17 января 2010

К сожалению, List<T> не отменяет Equals или GetHashCode. Это означает, что даже после того, как вы исправили объявление класса, вам нужно будет выполнить сравнение самостоятельно:

public bool Equals(Foo<T> foo)
{
    // These need to be calls to ReferenceEquals if you are overloading ==
    if (foo == null)
    {
        return false;
    }
    if (foo == this)
    {
        return true;
    }
    // I'll assume the lists can never be null
    if (lst.Count != foo.lst.Count)
    {
        return false;
    }
    for (int i = 0; i < lst.Count; i++)
    {
        if (!lst[i].Equals(foo.lst[i]))
        {
            return false;
        }
    }
    return true;
}

public override int GetHashCode()
{
    int hash = 17;
    foreach (T item in lst)
    {
        hash = hash * 31 + item.GetHashCode();
    }
    return hash;
}

public override bool Equals(Object obj)
{
    // Note that Equals *shouldn't* throw an exception when compared
    // with an object of the wrong type
    return Equals(obj as Foo<T>);
}

Я бы лично очень внимательно подумал, прежде чем перегружать == и! = Тоже. Если вы делаете решаете реализовать их, вам следует подумать о случаях, когда одно или оба значения равны нулю:

public static bool operator ==(Foo<T> f1, Foo<T> f2)
{
   if (object.ReferenceEquals(f1, f2))
   {
       return true;
   }
   if (object.ReferenceEquals(f1, null)) // f2=null is covered by Equals
   {
       return false;
   }
   return f1.Equals(f2);
}
2 голосов
/ 17 января 2010

Попробуйте это.

    public class Foo<T> : IEquatable<Foo<T>> where T : struct
    {
        List<T> lst;

        #region IEquatable<T> Members

        public bool Equals(Foo<T> other)
        {
            if (lst.Count != other.lst.Count)
            {
                return false;
            }

            for (int i = 0; i < lst.Count; i++)
            {
                if (!lst[i].Equals(other.lst[i]))
                {
                    return false;
                }
            }
            return true;
        }

        #endregion

        public override bool Equals(object obj)
        {
            var other = obj as Foo<T>;
            return other != null && Equals(other);
        }


    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...