Почему C # не привязывается правильно к универсальным переопределенным методам?

Я определил следующие классы и методы:

 using System;
 using System.Linq.Expressions;
 using System.Windows.Forms;

 public class ReturnValue<T, S> {}

 public class Something<T>
 {
     // Sorry about the odd formatting. Trying to get it to fit nicely...
     public ReturnValue<T, C>
     Do<C, S>(C control, Expression<Func<C, S>> controlProperty)
     where C : Control
     {
         return new ReturnValue<T, C>();
     }

     public ReturnValue<T, ToolStripItem>
     Do<S>(ToolStripItem control, Expression<Func<ToolStripItem, S>> controlProperty)
     {
         return new ReturnValue<T, ToolStripItem>();
     }
 }

Это прекрасно компилируется. Ух! Почти на месте. Затем я пытаюсь использовать его позже с таким кодом:

 var toolStripItem = new ToolStripStatusLabel();

 var something = new Something<string>();
 something.Do(toolStripItem, t => t.Text); // Does not compile

Это, однако, умирает со следующим сообщением об ошибке

Тип ToolStripStatusLabel не может использоваться в качестве параметра типа C в универсальном типе или методе Something .Do (C, Выражение >) . Не существует неявного преобразования ссылки из ToolStripStatusLabel в Control .

Мне кажется, что компилятор C # в этом случае потерпел неудачу, хотя эти два метода не создают набор неоднозначных объявления методов. Элемент управления и ToolStripStatusLabel существуют как одноуровневые элементы в дереве наследования Компонента . Я бы подумал, что у компилятора будет достаточно информации, чтобы правильно связать вызов метода в клиентском коде.

Однако, если я сделаю то же самое с моими родными классами, то все компилируется нормально.

 public class Parent {}
 public class Child1 : Parent {}
 public class Child2 : Parent {}

 public class Something2<T>
 {
     public ReturnValue<T, C>
     Do<C, S>(C control, Expression<Func<C, S>> controlProperty)
     where C : Child1
     {
         return new ReturnValue<T, C>();
     }

     public ReturnValue<T, Child2>
     Do<S>(Child2 control, Expression<Func<Child2, S>> controlProperty)
     {
         return new ReturnValue<T, Child2>();
     }
 }

 var child2 = new Child2();
 var something2 = new Something2<string>();
 something2.Do(child2, c => c.GetType()); // Compiles just fine

Может ли кто-нибудь пролить свет на то, что я сделал не так, если что-нибудь?

8
задан BoltClock 7 January 2011 в 17:13
поделиться