¿Hay una etiqueta genérica "anónima" en C#, como "?" ¿En Java?
Pregunta
En Java, se puede declarar una variable parametrizada por un tipo genérico "desconocido", que tiene este aspecto:
Foo<?> x;
¿Existe una construcción equivalente a este signo de interrogación en C#?
Solución
La respuesta corta es no.No existe una característica equivalente en C#.
Una solución alternativa, desde C# desde la perspectiva de un desarrollador de Java por Dare Obasanjo:
En ciertos casos, es posible que sea necesario crear un método que pueda operar en estructuras de datos que contengan cualquier tipo en lugar de aquellas que contienen un tipo específico (por ejemplo,un método para imprimir todos los objetos en una estructura de datos) y al mismo tiempo aprovechar los beneficios de la tipificación segura en genéricos.El mecanismo para especificar esto en C# es a través de una característica llamada inferencia de tipos genéricos, mientras que en Java esto se hace usando tipos comodín.Los siguientes ejemplos de código muestran cómo ambos enfoques conducen al mismo resultado.
Código 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);
}
}
Código 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);
}
}
Otros consejos
AFAIK no puedes hacer eso en C#.Lo que hace el BCL y hay muchos ejemplos es crear una clase que no es genérica y luego crear una clase genérica que hereda el comportamiento base de la anterior.Vea el ejemplo a continuación.
class Foo
{
}
class Foo<T> : Foo
{
}
Puedes escribir algo como esto:
Foo t = new Foo<int>();
Si bien es cierto que no es un enfoque limpio, utilizar Foo<object> x
también puede ser adecuado.
No existe una sintaxis equivalente en C#.
No es (del todo) cierto que no exista un equivalente en C#.No existe un equivalente estático que pueda usar como tipo o llamar a métodos, es cierto.Para eso, use la respuesta de jorge.
Por otro lado, a veces se necesita la idea equivalente para reflexionar, y ahí hay un equivalente.Si usted tiene:
interface IFoo<T>
{
T Bar(T t, int n);
}
puedes conseguir un Type
que representa IFoo<int>
usando typeof(IFoo<int>)
.Menos conocido, y una respuesta parcial a su pregunta, es que también puede obtener un Type
que representa IFoo<T>
usando typeof(IFoo<>)
.
Esto es útil cuando quieres usar IFoo<T>
para algunos T
a través de la reflexión y no lo sabré T
hasta el tiempo de ejecución.
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, en realidad no existe el mismo concepto en C#.Necesitaría hacer referencia a una clase base de Foo (tal vez un Foo no genérico), o hacer que el método en el que está trabajando sea genérico (para que pueda consultar Foo y dejar que la persona que llama a su método determine qué T es).
Espero que ayude.