Сравнение элементов поля со списком и предупреждения компилятора
-
01-07-2019 - |
Вопрос
В 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)
}
Дайте мне знать.Удачи!Я исхожу из памяти, надеюсь, я ничего не ошибся.:о)