J'ai défini les classes et méthodes suivantes:Pourquoi C# ne se lie-il pas correctement aux méthodes génériques surchargées?
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>();
}
}
Cette compile bien. Woo hoo! À mi-chemin. Ensuite, j'essaie de l'utiliser plus tard avec le code comme ceci:
var toolStripItem = new ToolStripStatusLabel();
var something = new Something<string>();
something.Do(toolStripItem, t => t.Text); // Does not compile
Ceci, cependant, meurt avec le message d'erreur suivant
Le type
ToolStripStatusLabel
ne peut pas être utilisé comme paramètre de typeC
dans le type générique ou méthodeSomething<T>.Do<C,S>(C, Expression<Func<C,S>>)
. Il n'y a pas de conversion de référence implicite deToolStripStatusLabel
àControl
.
Il me semble que le compilateur C# a échoué dans ce cas, bien que les deux méthodes ne créent pas un ensemble de déclarations de méthode ambiguës. Control
et ToolStripStatusLabel
existent en tant que frères et sœurs dans l'arbre d'héritage de Component
. Je pense que le compilateur aurait assez d'informations pour lier correctement l'invocation de méthode dans le code client.
Cependant, si je fais la même chose avec mes propres classes de frères et sœurs, alors tout se compile bien.
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
Quelqu'un peut-il faire la lumière sur ce que j'ai fait de mal, si quelque chose?
Jon, c'est une excellente explication. Je vous remercie. – realistschuckle
Alors pourquoi le deuxième exemple compile-t-il? –
BlueRaja (en plus d'un grand nom) écrit correctement, que j'ai pensé après avoir considéré l'explication plus loin. Un aperçu, Jon? – realistschuckle