Сравнение элементов поля со списком и предупреждения компилятора

StackOverflow https://stackoverflow.com/questions/98622

Вопрос

В VisualStudio (Pro 2008) я только что заметил некоторое непоследовательное поведение и задался вопросом, есть ли за этим какое-либо логическое обоснование.

В проекте WinForms, если я использую строку

if(myComboBox.Items[i] == myObject)

Я получаю предупреждение компилятора о том, что могу получить «Возможные непреднамеренные ссылки» при сравнении объекта типа с типом MyObject.Справедливо.

Однако, если вместо этого я использую интерфейс для сравнения:

if(myComboBox.Items[i] == iMyInterface)

предупреждение компиляции исчезает.

Может кто-нибудь подумать, есть ли какая-то логическая причина, почему это должно происходить, или это просто артефакт компилятора, который не проверяет интерфейсы на наличие предупреждений сравнения.Есть предположения?

РЕДАКТИРОВАТЬ В моем примере поле со списком было привязано к списку, но этот список был создан с помощью list<IMyInterface>.Cast<MyObject>().ToList<MyObject>()

Это как если бы компилятор все еще предполагал, что я привязываюсь к списку IMyInterface.

(Методы объекта и интерфейса были изменены для защиты невиновных)

Это было полезно?

Решение

Предупреждение компиляции для первого примера связано с тем, что любой пользовательский оператор == для вашего класса будет игнорироваться, а ссылки сравниваться (возможно, не так, как вы предполагали, отсюда и предупреждение).

Невозможно указать, что оператор должен быть переопределен в интерфейсе, поэтому это будет всегда быть эталонным сравнением.Предупреждение не требуется, поскольку этого следует ожидать всегда.

Вот пример переопределения оператора ==:

class Program
{
    static void Main(string[] args)
    {
        object t1 = new MyTest() { Key = 1 };
        MyTest t2 = new MyTest() { Key = 1 };

        Console.WriteLine((MyTest)t1 == t2); // Uses overriden == operator, returns true
        Console.WriteLine(t1 == t2); // Reference comparison, returns false
    }
}

public class MyTest
{
    public int Key { get; set; }

    public override bool Equals(object obj)
    {
        return this.Key == (obj as MyTest).Key;
    }

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

    public static bool operator ==(MyTest t1, MyTest t2)
    {
        return t1.Equals(t2);
    }

    public static bool operator !=(MyTest t1, MyTest t2)
    {
        return !t1.Equals(t2);
    }

}

Класс MyTest считается равным, если свойство Key равно.Если бы вы создавали интерфейс, вы не могли бы указать, что он должен включать собственный оператор ==, и поэтому сравнение всегда будет ссылочным сравнением (и, следовательно, ложным в случае нашего примера кода).

Другие советы

Лагердалек,

Предупреждение генерируется, поскольку перед сравнением необходимо привести элемент из коллекции Items обратно к исходному типу, который был привязан к полю со списком;в противном случае вы можете получить неожиданные результаты, как предупреждает компилятор.

Вот пример:

myComboBox.DataSource = Collection<Car>;

Итак, если поле со списком привязано к коллекции машина объекты, которые вы бы вернули перед сравнением:

if((car)myComboBox.Items[i] == thisCar)

Тогда вы не должны получать никаких предупреждений.

Другой метод, который вы можете сделать:

using(myComboBox.Items[i] as car){
 if(myComboBox.Items[i] == thisCar)
}

Дайте мне знать.Удачи!Я исхожу из памяти, надеюсь, я ничего не ошибся.:о)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top