ho definito le seguenti classi e metodi:Perché C# non si associa correttamente ai metodi sovrascritti generici?
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>();
}
}
Questo compila bene. Woo hoo! A metà strada lì. Poi, cerco di utilizzare in un secondo momento con il codice come questo:
var toolStripItem = new ToolStripStatusLabel();
var something = new Something<string>();
something.Do(toolStripItem, t => t.Text); // Does not compile
Questo, però, muore con il seguente messaggio di errore
Il tipo
ToolStripStatusLabel
non può essere utilizzato come tipo di parametroC
nel tipo generico o metodoSomething<T>.Do<C,S>(C, Expression<Func<C,S>>)
. Non esiste alcuna conversione implicita del riferimento daToolStripStatusLabel
aControl
.
Mi sembra che il compilatore C# abbia fallito in questo caso sebbene i due metodi non creino un insieme di dichiarazioni di metodi ambigue. Control
e ToolStripStatusLabel
esistono come fratelli nell'albero di ereditarietà di Component
. Penserei che il compilatore avrebbe abbastanza informazioni per associare correttamente l'invocazione del metodo nel codice client.
Tuttavia, se faccio la stessa cosa con le mie classi di pari livello, quindi tutto va bene.
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
Qualcuno può far luce su ciò che ho fatto di sbagliato, semmai?
Jon, questa è un'ottima spiegazione. Grazie. – realistschuckle
Quindi, perché compila il secondo esempio? –
BlueRaja (oltre ad un grande nome) scrive correttamente, cosa a cui ho pensato dopo aver considerato la spiegazione ulteriormente. Qualche idea, Jon? – realistschuckle