Я определил следующие классы и методы:
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>();
}
}
Это хорошо компилируется. Woo Hoo! Почти на месте. Затем я попытаюсь использовать его позже с кодом, подобным этому:
var toolStripItem = new ToolStripStatusLabel();
var something = new Something<string>();
something.Do(toolStripItem, t => t.Text); // Does not compile
Это, однако, умирает со следующим сообщением об ошибке
Тип ToolStripStatusLabel
нельзя использовать в качестве параметра типа C
в универсальном типе или методе Something<T>.Do<C,S>(C, Expression<Func<C,S>>)
. Не существует неявного преобразования ссылок из ToolStripStatusLabel
в Control
.
Мне кажется, что в этом случае произошел сбой компилятора C #, хотя эти два метода не создают набор неоднозначных объявлений методов. Control
и ToolStripStatusLabel
существуют как братья и сестры в дереве наследования Component
. Я думаю, что у компилятора будет достаточно информации, чтобы правильно связать вызов метода в клиентском коде.
Однако, если я делаю то же самое с моими собственными классами братьев и сестер, то все компилируется нормально.
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
Может кто-нибудь пролить свет на то, что я сделал неправильно, если что-нибудь?