我有一个工厂类,它返回从抽象类型继承的具体实例。这些具体实例的数据类型也具有通用属性,因为每个实例都需要不同的数据类型。 Data属性也存在于抽象类型上,因为它是在工厂中设置的。
public static class FactoryClass
{
public static TType CreateNewClass<TType>(object data)
where TType : AbstractClass<object>, new()
{
var newClass = new TType {Data = data};
// do some stuff
// keep track of all created types in a list
List.Add(newClass);
return newClass;
}
private List<AbstractClass<object>> MyList = new List<AbstractClass<object>>()
}
public abstract class AbstractClass<TData>
{
internal AbstractClass()
{
// do constructor things
}
protected SomeCommonFunction()
{
// common code for abstract base class
}
public abstract void DoSomethingToData();
TData Data;
}
public class ExampleClass : AbstractClass<string[]>
{
public override void DoSomethingToData()
{
// sort the strings or something
// call the abstract code
}
}
当我尝试拨打FactoryClass.CreateNewClass<ExampleClass>(myStringArray)
时,我收到一条错误消息,表明它需要投放到AbstractClass<object>
有没有更好的方法来做我想做的事情?
答案 0 :(得分:3)
这就是问题所在:
where TType : AbstractClass<object>
该约束正是编译器所抱怨的约束。
听起来我觉得你真的想要这样的东西:
public static TContainer CreateNewClass<TContainer, TData>(TData data)
where TContainer : AbstractClass<TData>, new()
不幸的是,然后需要您为方法指定两个类型的参数 - 但至少就您正在使用的数据类型而言是安全的。您可以通过创建两个通用方法和在它们之间使用的单独类来解决此问题,从而允许您编写类似的内容:
FactoryClass.For(myStringArray).CreateNewClass<ExampleClass>();
For
方法将返回类型参数为string[]
的泛型类型,然后CreateNewClass
将是一个实例方法,它采用数据类型的容器类型。
但是,您的列表无法以当前形式运行。您可能想为AbstractClass
:
public abstract class AbstractClass
{
// Anything which doesn't use TData
}
然后:
public abstract class AbstractClass<TData> : AbstractClass
此时,工厂中的列表将是List<AbstractClass>
;你不会以编译时安全的方式知道每个条目的数据类型......这完全合理,因为每个元素都可以使用不同的类型。
(哦,如果你想从静态方法访问它,你的列表字段当然需要是静态的......)