usando tipos tipo ser referencia que objetos lista instanciar genericos genericas debe colecciones clases c# list class generics dynamic

c# - ser - tipos de genericos



Almacenar una lista de diferentes tipos genéricos en una clase (4)

Adjunto una foto de lo que estoy tratando de hacer. Digamos que tengo una lista de T en una clase

public class MyClass<T> where T : IMyInterface { public List<T> list = new List<T>; }

Ahora, otra clase tiene una lista de MyClass.

public class AnotherClass { public List<MyClass<IMyInterface>> list = new List<MyClass<IMyInterface>>; }

¿Cuál es la T que debo poner para MyClass? Si pongo T, entonces se supone que todos los tipos en esa clase son iguales, pero no lo es. Si pongo IMyInterface, no podría lanzar IMyInterface a T al acceder a estas clases.

new AnotherClass().list.Add(new MyClass<T>());

¿Cuál es el tipo aquí ahora? La lista en el tipo genérico de AnotherClass es IMyInterface pero lo que quiero agregar es T, que TI quiere ser dinámico pero aún están bajo IMyInterface.


¿Usando covariant ?

public interface IMyInterface { } public class A : IMyInterface { } public class B : IMyInterface { } // Covariant interface public interface IMyClass<out T> { } // Inherit IMyClass public class MyClass<T> : IMyClass<T> where T : IMyInterface { public List<T> list = new List<T>(); } public class AnotherClass { // Note the list using IMyClass instead of the concrete MyClass type // The covariant interface type would allow any IMyInterface conversion public List<IMyClass<IMyInterface>> list = new List<IMyClass<IMyInterface>>(); public AnotherClass() { this.list.Add(new MyClass<A>()); this.list.Add(new MyClass<B>()); } }


Creo que quiere decir que quiere tener varios tipos genéricos en una lista, por ejemplo:

var ac = new AnotherClass(); ac.list.Add(new MyClass<int>()); ac.list.Add(new MyClass<bool>()); ac.list.Add(new MyClass<double>());

Una forma sencilla de hacer esto es definir su lista como una lista de objetos:

public class AnotherClass { public List<object> list = new List<object>(); }

El problema aquí es que puedes hacer lo que quieras en esa lista, no solo tu clase genérica. Lo siguiente también sería posible:

list.Add(1); list.Add("hello");

La única forma en que podría restringir lo que puede agregar es usar una clase base abstracta.

public class MyClassBase { } public class MyClass<T> : MyClassBase where T : IMyInterface { public List<T> list = new List<T>(); }

Y luego tener una lista de esos:

public class AnotherClass { public List<MyClassBase> list = new List<MyClassBase>(); }

Aún tendrás que hacer una comprobación de tipos al acceder a esos objetos, pero al menos sabrás que los objetos están restringidos a aquellos que heredan MyClassBase


Creo que su problema es que no necesita usar genéricos para esto. Si especifica su clase como:

public class MyClass { public IList<IMyInterface> list = new List<IMyImterface>(); }

Luego puede agregar a esta cualquier instancia de cualquier clase que implemente la interfaz.

public class DummyClass : IMyInterface {} public class AnotherClass { { IList<MyClass> anotherList = new List<MyClass>(); public void AMethod() { MyClass myList = new MyClass(); myList.Add(new DummyClass()); anotherList.Add(myList); } }

Luego puede acceder a todos los elementos de la lista como IMyInterface directamente, o si desea elementos de una clase específica, puede usar LINQ:

foreach (IMyImterface item in myList.Where(x => x is DummyClass)) { DummyClass dummy = (DummyClass)item; } // or foreach (IMyImterface item in myList.OfType<DummyClass>()) { DummyClass dummy = (DummyClass)item; }

O simplemente puedes probar el casting y verificar si es nulo:

foreach (IMyIntetface item in myList) { DummyClass dummy = item as DummyClass; if (dummy != null) { // do something } }


La T en un genérico debe ser la misma durante toda su vida útil.

para un ejemplo

var a = new MyClass<int>(); a.list.Add(1); //since a''s generic T is declared as int the list is now also int var b = new MyClass<string>() b.list.Add("string"); //in b its now declared as a string and avccepts only string

Así que cuando estás haciendo esto.

var c = new MyClass<IMyInterface>(); c.list.Add(ObjectImplementingIMyInterface); //You must add something that implements IMyInterface

Lo único que sabe sobre el contenido es que implementa IMyInterface ahora, si desea dividir la ejecución del objeto, debe verificar el tipo del objeto a través de la reflexión.

if(c.list[i].GetType() == typeof(ClassA_IMyInterface) { //Execute on ClassA_IMyInterface //If you are after the ClassA //and want to run something speciffic for it the cast ClassA clA = = (ClassA)c.list[i]; //Now you have access to the implementation of ClassA instead of just the interface } else if (c.list[i].GetType() == typeof(ClassB_IMyInterface) { //Execute on ClassB_IMyInterface }

Aquí hay un ejemplo que hice en ConsoleApplication que muestra cómo se desarrolla.

public class MyClass<T> where T : IMyInterface { public List<T> list = new List<T>(); } public interface IMyInterface { } public class Foo : IMyInterface { } public class Bar : IMyInterface { } public class FooBar { public void Test() { var content = new MyClass<IMyInterface>(); content.list.Add(new Foo()); if (content.list[0] is Foo) { //Execute on Foo var g = (Foo)content.list[0]; //Now you can access Foo''s methods and not only the Interfaces Console.WriteLine("Foo"); } else if (content.list[0] is Bar) { //Execute on Bar var g = (Bar)content.list[0]; //Now you can access Bar''s methods and not only the Interfaces Console.WriteLine("Bar"); } } }