Я определил следующие классы и методы:
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
Может ли кто-нибудь пролить свет на то, что я сделал не так, если что-нибудь?