Как проверить, является ли место в массиве тем же объектом, что и другой объект? - PullRequest
0 голосов
/ 27 апреля 2020

У меня есть следующий код:

public static bool contains(Team [] ts, Team t)
{
    for(int i=0; i<ts.Length; i++)
    {
        if (ts[i]== t)
        {
            return true;
        }
    }
    return false;
}

Но почему-то всегда возвращается false. Когда я использую Equals, он выдает NullReferenceException, и я не знаю, что еще делать.

Ответы [ 3 ]

2 голосов
/ 27 апреля 2020

В вашем вопросе есть несколько моментов, которые стоит обсудить.

Для сравнения ts[i] и t вы используете оператор равенства ==. По умолчанию этот оператор выполняет проверку равенства ссылок между двумя операндами, другими словами, это эквивалентно вызову object.ReferenceEquals(ts[i], t). Это означает, что два операнда считаются равными, если и только если они являются двумя ссылками на одну и ту же ячейку памяти.

Если это не равенство семанти c, которое вы собираетесь использовать для класса Team, вам необходимо переопределить методы Equals и GetHashCode и оба оператора == и !=. После этого ваш код будет автоматически использовать равенство semanti c, которое вы определили в своих переопределениях. Начните с здесь , если вам нужно больше подробностей об этом.

Второй важный момент связан с NullReferenceException. Если вы позвоните t[i].Equals(t), а t[i] - это ссылка null, тогда вы получите NullReferenceException. Таким образом, у вас есть следующие варианты:

  • проверяет, является ли t[i] ссылка null перед вызовом Equals
  • , вместо оператора
  • используется оператор равенства stati c метод object.Equals вместо

Последнее, но не менее важное, как указано в других ответах на то, что вы пытаетесь сделать , уже реализовано в. NET framework и вам следует использовать уже существующий Contains метод расширения.

Обратите внимание, что при использовании уже существующего Содержит метод расширения вам все равно необходимо переопределить элементы равенства Team класс, как объяснено выше.

В качестве альтернативы вы можете решить использовать эту перегрузку метода расширения Contains , которая позволяет вам указать желаемое равенство semanti c на сайте вызова с помощью пользовательского Сравнение равенства (реализация IEqualityComparer<Match> в вашем случае). Это может быть полезно, если по какой-либо причине имеет смысл определить несколько различных семантик равенства для класса Team (в зависимости от контекста). Если вы всегда хотите сравнить Match экземпляры, используя то же самое равенство semanti c, выберите первый вариант переопределения членов равенства класса (как описано выше) и используйте перегрузку Содержит только один параметр .

0 голосов
/ 27 апреля 2020

Один из способов сделать это - создать интерфейс с методом Equals, а затем класс реализовать этот интерфейс.

На вашем примере:

public interface IEqualable<T>
{
    public bool Equal(T t);
}

public class Team : IEqualable<Team>
{
    public string TeamName { get; set; }
    public bool Equal(Team t2)
    {
        if(t2 is null) return false; 
        if (this.TeamName == t2.TeamName)
            return true;
        return false;
    }
}

public class Program
{
    static void Main(string[] args)
    {
        var p = new Team[3] { new Team() { TeamName = "qwe" }, new Team() { TeamName = "asd" }, new Team() { TeamName = "qq" } };
        Console.WriteLine(contains(p, new Team { TeamName = "qq" }));
    }

    public static bool contains(Team[] ts, Team t)
    {
        for (int i = 0; i < ts.Length; i++)
        {
            if (ts[i].Equal(t))
            {
                return true;
            }
        }
        return false;
    }
}

Подробнее здесь

0 голосов
/ 27 апреля 2020

Обычно это хороший способ узнать, как. net фреймворк реализовал похожее поведение в своем коде.

Из . Net Источник :

    // Contains returns true if the specified element is in the ArrayList.
    // It does a linear, O(n) search.  Equality is determined by calling
    // item.Equals().
    //
    public virtual bool Contains(Object item) {
        if (item==null) {
            for(int i=0; i<_size; i++)
                if (_items[i]==null)
                    return true;
            return false;
        }
        else {
            for(int i=0; i<_size; i++)
                if ( (_items[i] != null) && (_items[i].Equals(item)) )
                    return true;
            return false;
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...