Existe-t-il un & # 8220; anonyme & # 8221; balise générique en C #, comme '?' en Java?
Question
En Java, on peut déclarer une variable paramétrée par un "inconnu". type générique, qui ressemble à ceci:
Foo<?> x;
Existe-t-il une construction équivalente à ce point d'interrogation, en C #?
La solution
La réponse courte est non. Il n’existe pas de fonctionnalité équivalente en C #.
Solution de contournement, tirée de C # du point de vue d'un développeur Java par Dare Obasanjo:
Dans certains cas, il peut être nécessaire de créer une méthode pouvant fonctionner sur des structures de données contenant tout type, contrairement à celles contenant un type spécifique (par exemple, une méthode permettant d’imprimer tous les objets d’une structure de données) tout en tirant parti des avantages de les avantages de la dactylographie forte dans les génériques. Le mécanisme permettant de spécifier cela en C # se fait via une fonctionnalité appelée inférence de type générique, alors qu'en Java, elle utilise des types génériques. Les exemples de code suivants montrent comment les deux approches aboutissent au même résultat.
Code C #
using System;
using System.Collections;
using System.Collections.Generic;
class Test{
//Prints the contents of any generic Stack by
//using generic type inference
public static void PrintStackContents<T>(Stack<T> s){
while(s.Count != 0){
Console.WriteLine(s.Pop());
}
}
public static void Main(String[] args){
Stack<int> s2 = new Stack<int>();
s2.Push(4);
s2.Push(5);
s2.Push(6);
PrintStackContents(s2);
Stack<string> s1 = new Stack<string>();
s1.Push("One");
s1.Push("Two");
s1.Push("Three");
PrintStackContents(s1);
}
}
Code Java
import java.util.*;
class Test{
//Prints the contents of any generic Stack by
//specifying wildcard type
public static void PrintStackContents(Stack<?> s){
while(!s.empty()){
System.out.println(s.pop());
}
}
public static void main(String[] args){
Stack <Integer> s2 = new Stack <Integer>();
s2.push(4);
s2.push(5);
s2.push(6);
PrintStackContents(s2);
Stack<String> s1 = new Stack<String>();
s1.push("One");
s1.push("Two");
s1.push("Three");
PrintStackContents(s1);
}
}
Autres conseils
class Foo
{
}
class Foo<T> : Foo
{
}
Vous pouvez écrire quelque chose comme ceci:
Foo t = new Foo<int>();
Bien que n'étant pas une approche propre, utilisez Foo < object > x
peut également convenir.
Il n'y a pas de syntaxe équivalente en C #.
Ce n'est pas (tout à fait) vrai qu'il n'y a pas d'équivalent en C #. Il n'y a pas d'équivalent statique que vous pouvez utiliser en tant que type ou en appelant des méthodes suffisamment vraies. Pour cela, utilisez la réponse de Jorge .
D’un autre côté, vous avez parfois besoin de l’idée équivalente pour la réflexion et il existe un équivalent. Si vous avez:
interface IFoo<T>
{
T Bar(T t, int n);
}
vous pouvez obtenir un type
qui représente IFoo < int >
en utilisant typeof (IFoo < int >)
. Une réponse partielle à votre question est moins connue. Vous pouvez également obtenir un type
qui représente IFoo < T >
en utilisant typeof (IFoo < > )
.
Cela est utile lorsque vous souhaitez utiliser IFoo < T >
pour certains T
par réflexion et si T
ne sera pas connu avant l'exécution.
Type theInterface = typeof(IFoo<>);
Type theSpecificInterface = theInterface.MakeGenericType(typeof(string));
// theSpecificInterface now holds IFoo<string> even though we may not have known we wanted to use string until runtime
// proceed with reflection as normal, make late bound calls / constructions, emit DynamicMethod code, etc.
Non, il n'y a pas vraiment le même concept en C #. Vous devrez vous référer à une classe de base de Foo (peut-être un Foo non générique) ou rendre la méthode que vous travaillez générique (afin que vous puissiez vous référer à Foo et laisser l'appelant de votre méthode déterminer est).
L’espoir que cela aide.