views:

213

answers:

2

In VisualStudio (Pro 2008), I have just noticed some inconsistent behaviour and wondered if there was any logical reasoning behind it

In a WinForms project, if I use the line

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

I get a compiler warning that I might get 'Possible unintended references' as I am comparing type object to type MyObject. Fair enough.

However, if I instead use an interface to compare against:

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

the compile warning goes away.

Can anyone think if there is any logical reason why this should happen, or just an artifact of the compiler not to check interfaces for comparison warnings. Any thoughts?

EDIT In my example, the combobox was bound to a List, but that list was generated using list<IMyInterface>.Cast<MyObject>().ToList<MyObject>()

Its as if the compiler is only taking still assuming I am binding to the List of IMyInterface.

(Object and Interface methods have been changed to protect the innocent)

A: 

Lagerdalek,

The warning is generated because you need to cast the item from the Items collection back into the orginal type that was bound to the combo box, before comparing; otherwise you may get unexpected results as the compiler warns.

Here is an example:

myComboBox.DataSource = Collection<Car>;

So if the combo box is bound to a collection of car objects you would cast them back before comparison:

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

Then you shouldn't get any warnings.

Another method you could do is:

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

Let me know. Good Luck! I'm going from memory, I hope I didn't mistype anything. :o)

Jason Stevenson
The strange thing i the combo is bound to a list of the object type, not the Interface type, BUT the list of object is generated from a list of interface using the Cast<>().ToList<>() functions. Very odd. Thanks for the input
johnc
Is the datasource really a list of "object" or a user-defined object (as you implied in your question)?
toast
Yes, that's correct. The datasource is not strongly typed. For this to work, there would need to be a strongly typed Listbox (eg. ListBox<Car>). For now, we're stuck with objects :(
Danny Tuppeny
+1  A: 

The compile warning for the first sample is because any custom == operator for your class would be ignored and the references compared (maybe not what you intended, hence the warning).

It's not possible to specify that an operator should be overridden on an interface, so this will always be a reference comparison. The warning is not needed because you should always expect this.

Here's an example of overriding the == operator:

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);
 }

}

The MyTest class is considered equal if the Key property is equal. If you were to create an interface, you cannot specify that it should include a custom == operator and therefore the comparison would always be a reference comparison (and therefore false in the case of our sample code).

Danny Tuppeny