我附上了一张我想要做的事情的照片。让我们说我在课堂上有一个T列表
public class MyClass<T>
where T : IMyInterface
{
public List<T> list = new List<T>;
}
现在,另一个类有一个MyClass列表。
public class AnotherClass
{
public List<MyClass<IMyInterface>> list = new List<MyClass<IMyInterface>>;
}
我应该为MyClass提供什么?如果我把T,那么它假定该类中的所有类型都是相同的,但它不是。如果我把IMyInterface,我在访问这些类时不能将IMyInterface转换为T.
new AnotherClass().list.Add(new MyClass<T>());
现在这里的类型是什么? AnotherClass泛型类型中的列表是IMyInterface,但我要添加的内容是T,我希望它是动态的,但它们仍然在IMyInterface下。
答案 0 :(得分: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
所以当你这样做时。
var c = new MyClass<IMyInterface>();
c.list.Add(ObjectImplementingIMyInterface); //You must add something that implements IMyInterface
你对内容的唯一了解就是它现在实现了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
}
这是我在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");
}
}
}
答案 1 :(得分:5)
我认为您的问题是您不需要使用泛型。如果您将课程指定为:
public class MyClass
{
public IList<IMyInterface> list = new List<IMyImterface>();
}
然后你可以添加任何实现该接口的类的实例。
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);
}
}
然后你可以直接从列表中访问所有项目,或者如果你想要特定类的项目,你可以使用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;
}
或者您可以尝试投射并检查是否为null:
foreach (IMyIntetface item in myList)
{
DummyClass dummy = item as DummyClass;
if (dummy != null)
{
// do something
}
}
答案 2 :(得分:3)
我认为你的意思是你想在一个列表中有多个泛型类型,例如:
var ac = new AnotherClass();
ac.list.Add(new MyClass<int>());
ac.list.Add(new MyClass<bool>());
ac.list.Add(new MyClass<double>());
一种简单的方法是将列表定义为对象列表:
public class AnotherClass
{
public List<object> list = new List<object>();
}
这里的问题是你可以对列表中的任何内容,而不仅仅是你的泛型类。以下也是可能的:
list.Add(1);
list.Add("hello");
限制你可以添加的内容的唯一方法是使用抽象基类。
public class MyClassBase
{
}
public class MyClass<T> : MyClassBase
where T : IMyInterface
{
public List<T> list = new List<T>();
}
然后列出一些:
public class AnotherClass
{
public List<MyClassBase> list = new List<MyClassBase>();
}
访问这些对象时,您仍然需要进行一些类型检查,但至少您知道对象仅限于继承MyClassBase的对象
答案 3 :(得分:2)
使用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>());
}
}