Je veux avoir une fonction d'impression générique ... PrintGeneric (T) ... dans le cas suivant, qu'est-ce qui me manque?
Comme toujours, votre aide/compréhension est appréciée ...
public interface ITest
{}
public class MyClass1 : ITest
{
public string myvar = "hello 1";
}
public class MyClass2 : ITest
{
public string myvar = "hello 2";
}
class DoSomethingClass
{
static void Main()
{
MyClass1 test1 = new MyClass1();
MyClass2 test2 = new MyClass2();
Console.WriteLine(test1.myvar);
Console.WriteLine(test2.myvar);
Console.WriteLine(test1.GetType());
PrintGeneric(test1);
PrintGeneric<test2.GetType()>(test2);
}
// following doesn't compile
public void PrintGeneric<T>(T test)
{
Console.WriteLine("Generic : " + test.myvar);
}
}
Il ne compile pas car T pourrait être n'importe quoi, et tout n'aura pas le champ myvar
.
Vous pouvez faire de myvar
une propriété sur ITest
:
public ITest
{
string myvar{get;}
}
et l'implémenter sur les classes en tant que propriété:
public class MyClass1 : ITest
{
public string myvar{ get { return "hello 1"; } }
}
puis mettez une contrainte générique sur votre méthode:
public void PrintGeneric<T>(T test) where T : ITest
{
Console.WriteLine("Generic : " + test.myvar);
}
mais dans ce cas, pour être honnête, il vaut mieux simplement passer un ITest:
public void PrintGeneric(ITest test)
{
Console.WriteLine("Generic : " + test.myvar);
}
Vous manquez au moins deux choses:
Sauf si vous utilisez la réflexion, les arguments de type doivent être connus au moment de la compilation, vous ne pouvez donc pas utiliser
PrintGeneric<test2.GetType()>
... bien que dans ce cas vous n'en ayez pas besoin de toute façon
PrintGeneric
ne sait rien de T
pour le moment, donc le compilateur ne peut pas trouver un membre appelé T
Options:
Placez une propriété dans l'interface ITest
et modifiez PrintGeneric
pour contraindre T
:
public void PrintGeneric<T>(T test) where T : ITest
{
Console.WriteLine("Generic : " + test.PropertyFromInterface);
}
Mettez une propriété dans l'interface ITest
et supprimez entièrement les génériques:
public void PrintGeneric(ITest test)
{
Console.WriteLine("Property : " + test.PropertyFromInterface);
}
Utilisez la frappe dynamique au lieu des génériques si vous utilisez C # 4
Dans votre méthode générique, T
n'est qu'un espace réservé pour un type. Cependant, le compilateur ne sait rien en soi sur le ou les types concrets utilisés lors de l'exécution, il ne peut donc pas supposer qu'ils auront un membre var
.
La façon habituelle de contourner cela est d'ajouter une contrainte de type générique à votre déclaration de méthode pour vous assurer que les types utilisés implémentent une interface spécifique (dans votre cas, il pourrait s'agir de ITest
):
public void PrintGeneric<T>(T test) where T : ITest
Ensuite, les membres de cette interface seraient directement disponibles dans la méthode. Cependant, votre ITest
est actuellement vide, vous devez y déclarer des éléments communs afin de permettre son utilisation dans la méthode.
Vous devrez fournir plus d'informations sur le type générique T
. Dans votre méthode PrintGeneric
actuelle, T
pourrait aussi bien être un string
, qui n'a pas de membre var
.
Vous souhaiterez peut-être remplacer var
par une propriété plutôt que par un champ
public interface ITest
{
string var { get; }
}
Et ajoutez une contrainte where T: ITest
à la méthode PrintGeneric
.
Vous devez définir quelque chose dans l'interface, comme:
public interface ITest
{
string Name { get; }
}
Implémentez ITest
dans vos classes:
public class MyClass1 : ITest
{
public string Name { get { return "Test1"; } }
}
public class MyClass2 : ITest
{
public string Name { get { return "Test2"; } }
}
Limitez ensuite votre fonction générique Print
à ITest
:
public void Print<T>(T test) where T : ITest
{
}
essayer
public void PrintGeneric<T>(T test) where T: ITest
{
Console.WriteLine("Generic : " + test.@var);
}
comme @Ash Burlaczenko a dit que vous ne pouvez pas nommer une variable après un mot-clé, si vous voulez vraiment que ce préfixe avec le symbole @ échappe au mot-clé
Vous ne pouvez pas accéder à var
avec le générique.
Essayez quelque chose comme
Console.WriteLine("Generic : {0}", test);
Et remplacer la méthode ToString
[1]
[1] http://msdn.Microsoft.com/en-us/library/system.object.tostring.aspx