Esiste un & # 8220; anonimo & # 8221; tag generico in C #, come "?" in Java?
Domanda
In Java, si può dichiarare una variabile parametrizzata da un "sconosciuto" tipo generico, che assomiglia a questo:
Foo<?> x;
Esiste un costrutto equivalente a questo punto interrogativo, in C #?
Soluzione
La risposta breve è no. Non esiste una funzione equivalente in C #.
Una soluzione alternativa, da C # dal punto di vista di uno sviluppatore Java di Dare Obasanjo:
In alcuni casi, potrebbe essere necessario creare un metodo in grado di operare su strutture di dati contenenti qualsiasi tipo rispetto a quelli che contengono un tipo specifico (ad esempio un metodo per stampare tutti gli oggetti in una struttura di dati) sfruttando comunque i vantaggi della tipizzazione forte in generici. Il meccanismo per specificare questo in C # è tramite una funzione chiamata inferenza di tipo generico mentre in Java questo viene fatto usando tipi di caratteri jolly. I seguenti esempi di codice mostrano come entrambi gli approcci portano allo stesso risultato.
Codice 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);
}
}
Codice 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);
}
}
Altri suggerimenti
AFAIK non puoi farlo in C #. Quello che fa il BCL e ci sono molti esempi che esiste per creare una classe che non è generica e quindi creare una classe generica che eredita il comportamento di base da quello precedente. Vedi esempio di seguito.
class Foo
{
}
class Foo<T> : Foo
{
}
Puoi scrivere qualcosa del genere:
Foo t = new Foo<int>();
Pur non essendo l'approccio pulito, usando Foo < object > x
può anche essere adatto.
Non esiste una sintassi equivalente in C #.
Non è (abbastanza) vero che non esiste un equivalente in C #. Non esiste un equivalente statico che puoi utilizzare come tipo o chiamare metodi su, abbastanza vero. Per questo, usa Risposta di Jorge .
D'altra parte, a volte hai bisogno dell'idea equivalente di riflessione, e lì c'è un equivalente. Se hai:
interface IFoo<T>
{
T Bar(T t, int n);
}
puoi ottenere un Type
che rappresenta IFoo < int >
usando typeof (IFoo < int >)
. Meno noto, e una risposta parziale alla tua domanda, è che puoi anche ottenere un Tipo
che rappresenta IFoo < T >
usando typeof (IFoo < > )
.
Questo è utile quando si desidera utilizzare IFoo < T >
per alcuni T
attraverso la riflessione e non si conosce T
fino al runtime.
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.
No, non c'è davvero lo stesso concetto in C #. Dovresti fare riferimento a una classe base di Foo (forse un Foo non generico), o rendere il metodo che stai lavorando in modo generico stesso (in modo da poter fare riferimento a Foo e lasciare che il chiamante del tuo metodo determini quale T è).
Spero che sia d'aiuto.