Existe-t-il un & # 8220; anonyme & # 8221; balise générique en C #, comme '?' en Java?

StackOverflow https://stackoverflow.com/questions/116830

  •  02-07-2019
  •  | 
  •  

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 #?

Était-ce utile?

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

Si vous le voulez bien, vous ne pouvez pas le faire en C #. Ce que fait la BCL et il existe de nombreux exemples pour créer une classe non générique, puis créer une classe générique qui hérite du comportement de base de la précédente. Voir l'exemple ci-dessous.

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top