qué - this en c#
Declarar una instancia de tipo genérico dinámicamente (7)
Esta pregunta ya tiene una respuesta aquí:
¿Es posible declarar una instancia de un genérico sin saber el tipo en tiempo de diseño?
Ejemplo:
Int i = 1;
List<typeof(i)> list = new List<typeof(i)>();
donde el tipo de yo podría ser cualquier cosa, en lugar de tener que hacer:
List<int> list = new List<int();
Consulte la respuesta de la pregunta similar "Crear dinámicamente un tipo genérico para plantilla" . La única diferencia es que están generando el tipo desde la línea de comandos, el resto debería ser capaz de adaptarse a sus necesidades.
Por otro lado, no puede llamar a typeof en una instancia para obtener el tipo de instancia (por ejemplo, "i" llama a GetType ():
Type intType = i.GetType();
Creo que lo mejor que vas a poder hacer es algo como esto:
static void Main(string[] args)
{
int i = 1;
var thelist = CreateList(i);
}
public static List<T> CreateList<T>(T t)
{
return new List<T>();
}
Seguro que puedes hacer eso, no tienen que ser arreglados en tiempo de compilación, como las plantillas en c ++.
Un ejemplo que es similar aquí: http://geekswithblogs.net/marcel/archive/2007/03/24/109722.aspx
Si aún desea escribir .Add (), .Remove (), for foreach, etc., puede tratar la Lista como un "viejo" System.Collections.IList regular, ya que afortunadamente esta interfaz está implementada por List <T>.
Y dado que todas las demás respuestas publicadas a esta pregunta muestran casi todas las demás formas posibles de crear una instancia de una Lista <T> dinámicamente, mostraré una última forma de hacerlo. Yo personalmente uso este método al crear instancias genéricas, cuando realmente no sé nada sobre el tipo en tiempo de compilación, y el tipo debe pasar como una cadena, tal vez proveniente del archivo de configuración de la aplicación. En este ejemplo, T es System.String por simplicidad, pero podría ser cualquier cosa:
Type T = typeof ( string ); // replace with actual T
string typeName = string.Format (
"System.Collections.Generic.List`1[[{0}]], mscorlib", T.AssemblyQualifiedName );
IList list = Activator.CreateInstance ( Type.GetType ( typeName ) )
as IList;
System.Diagnostics.Debug.Assert ( list != null ); //
list.Add ( "string 1" ); // new T
list.Add ( "string 2" ); // new T
foreach ( object item in list )
{
Console.WriteLine ( "item: {0}", item );
}
Si no conoce el tipo en tiempo de compilación, pero quiere el tipo real (es decir, no List<object>
) y no está en un método / tipo genérico con el parámetro de tipo apropiado, entonces tiene que usar la reflexión .
Para simplificar el reflejo, a veces introduje un nuevo tipo o método genérico en mi propio código, por lo que puedo llamarlo por reflexión, pero luego uso genéricos normales después de eso. Por ejemplo:
object x = GetObjectFromSomewhere();
// I want to create a List<?> containing the existing
// object, but strongly typed to the "right" type depending
// on the type of the value of x
MethodInfo method = GetType().GetMethod("BuildListHelper");
method = method.MakeGenericMethod(new Type[] { x.GetType() });
object list = method.Invoke(this, new object[] { x });
// Later
public IList<T> BuildListHelper<T>(T item)
{
List<T> list = new List<T>();
list.Add(item);
return list;
}
Por supuesto, después de eso no se puede hacer mucho con la lista si no se sabe el tipo ... es por eso que este tipo de cosas a menudo se cae. Sin embargo, no siempre - He usado algo como el anterior en algunas ocasiones, donde el sistema de tipos simplemente no me deja expresar todo lo que necesito de forma estática.
EDITAR: Tenga en cuenta que aunque estoy llamando a Type.GetMethod en el código anterior, si iba a ejecutarlo mucho probablemente querría simplemente llamarlo una vez; después de todo, el método no va a cambiar. Es posible que pueda hacerlo estático (podría hacerlo en el caso anterior) y probablemente también desee hacerlo privado. Lo dejé como un método de instancia pública para la simplicidad de la llamada a GetMethod en el código de muestra; de lo contrario, necesitaría especificar los indicadores de enlace apropiados.
Si no conoce el tipo en tiempo de diseño, diría que tiene una lista de OBJETOS (la clase base para todos los demás tipos).
List<object> list = new List<object>();
También puede usar Activator.CreateInstance. Fragmento de código de ejemplo:
public class BaseRepository<T> where T : DataContext
{
protected T _dc;
public BaseRepository(string connectionString)
{
_dc = (T) Activator.CreateInstance(typeof(T), connectionString);
}
public void SubmitChanges()
{
_dc.SubmitChanges();
}
}