在类中存储不同泛型类型的列表

Lee*_*ong 19 c# generics class list dynamic

班级结构

我附上了一张我想要做的事情的照片.假设我在课堂上有一个T列表

public class MyClass<T> 
    where T : IMyInterface
{
    public List<T> list = new List<T>;
}
Run Code Online (Sandbox Code Playgroud)

现在,另一个类有一个MyClass列表.

public class AnotherClass
{
    public List<MyClass<IMyInterface>> list = new List<MyClass<IMyInterface>>;
}
Run Code Online (Sandbox Code Playgroud)

我应该为MyClass提供什么?如果我把T,那么它假设该类中的所有类型都相同,但事实并非如此.如果我把IMyInterface,我无法在访问这些类时将IMyInterface转换为T.

new AnotherClass().list.Add(new MyClass<T>()); 
Run Code Online (Sandbox Code Playgroud)

现在这里的类型是什么?AnotherClass泛型类型中的列表是IMyInterface,但我要添加的是T,TI希望它是动态的,但它们仍然在IMyInterface下.

Tho*_*ian 6

T在通用必须是通过了其寿命相同.

举个例子

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
Run Code Online (Sandbox Code Playgroud)

所以当你这样做的时候.

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

您对内容的唯一了解是它IMyInterface现在实现如果您想要拆分对象的执行,那么您必须通过反射检查对象的类型.

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
}
Run Code Online (Sandbox Code Playgroud)

这是我在ConsoleApplication中做的一个示例,展示了它的布局.

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");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Tim*_*ter 5

我认为您的意思是您希望在一个列表中包含多个泛型类型,例如:

var ac = new AnotherClass();
ac.list.Add(new MyClass<int>()); 
ac.list.Add(new MyClass<bool>()); 
ac.list.Add(new MyClass<double>());
Run Code Online (Sandbox Code Playgroud)

执行此操作的一个简单方法是将列表定义为对象列表:

public class AnotherClass
{
    public List<object> list = new List<object>();
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是您可以在该列表中添加任何您喜欢的内容,而不仅仅是您的通用类。以下也是可能的:

list.Add(1); 
list.Add("hello"); 
Run Code Online (Sandbox Code Playgroud)

限制可以添加的内容的唯一方法是使用抽象基类。

public class MyClassBase 
{

}
public class MyClass<T> : MyClassBase
    where T : IMyInterface
{
    public List<T> list = new List<T>();
}
Run Code Online (Sandbox Code Playgroud)

然后列出这些内容:

public class AnotherClass
{
    public List<MyClassBase> list = new List<MyClassBase>();
}
Run Code Online (Sandbox Code Playgroud)

访问这些对象时,您仍然需要进行一些类型检查,但至少您会知道这些对象仅限于继承 MyClassBase 的对象


Ste*_*ris 5

我认为您的问题是您不需要使用泛型.如果您将类指定为:

public class MyClass
{
    public IList<IMyInterface> list = new List<IMyImterface>();
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以添加任何实现该接口的类的实例.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以直接访问列表中的所有项目作为IMyInterface,或者如果你想要特定类的项目,你可以使用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;
}
Run Code Online (Sandbox Code Playgroud)

或者您可以尝试转换并检查是否为null:

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