我有接口和3个派生它的类,但是如何为每个类型使用1个变量?
public interface IBuilder<T> where T: System.IConvertible{}
public class SimpleBuilder : IBuilder<SimpleCollagePatterns>{}
public class CreativeBuilder : IBuilder<CreativeCollagePatterns>{}
public class ShapeBuilder : IBuilder<ShapeCollagePatterns>{}
我需要在必要时创建类的实例
我有IBuilder<IConvertible> currentBuilder
变量,但我无法创建任何Builder
this.currentBuilder = new SimpleBuilder(); //Doesn`t work
只有当我将IBuilder<IConvertible> currentBuilder
更改为IBuilder<SimpleCollagePatterns> currentBuilder
或其他类型时,我才能创建此类型的构建器,但我需要能够创建任何类型
答案 0 :(得分:0)
我遇到了同样的情况。但最终发现没有解决方案。在运行时无法创建任何类型的对象。正如您所说,将IBuilder currentBuilder更改为IBuilder currentBuilder是为SimpleBuilder类型创建对象的唯一方法。同样适用于其他情况。
答案 1 :(得分:0)
如果你真的想在所有场景中使用一个变量,你总是可以将它定义为一个简单的对象来保持实例并使用IS运算符在必要时查看它实际上是哪种类型:
if(this.currentBuilder是SimpleBuilder) { }
答案 2 :(得分:0)
我相信您需要让您的IBuilder协变,请参阅https://msdn.microsoft.com/en-us/library/dd997386(v=vs.110).aspx
public interface IBuilder<out T>
答案 3 :(得分:0)
您想要阅读的内容称为协方差,在接口声明中的泛型类型参数旁边用关键字out
表示。
public interface IBuilder<out T> where T: System.IConvertible{}
这将允许您声明类型为IBuilder<IConvertible>
的变量并指定例如。 SimpleBuilder
它,你只需要知道应用协方差的后果,最重要的是,用简单的话来说,泛型类型只能用作类型成员的返回类型。
如果您无法更改IBuilder
界面,则无法为所有情况创建变量。
有关详细信息,您可以研究SO,例如。 Difference between Covariance & Contra-variance或在源头阅读,例如。 https://msdn.microsoft.com/en-us/library/mt654055.aspx
答案 4 :(得分:0)
特别是如果SimpleCollagePatterns
由实现特定接口的类(在这种情况下为ShapeBuilder
)专门使用,则您不需要协方差。
有一种简单的设计模式仅依赖于继承。
例如:
public interface IBuilder {
void Build();
}
public interface IBuilder<T> : IBuilder {
T BuildParameter {get;}
}
注意:BuildParameter
对应于您的BuildCollagePattern
然后你可以这样实现接口:
public class SpecificBuilder : IBuilder<Int32> {
// The specific constructor
public SpecificBuilder(int param) { BuildParameter = param; }
// Implement from IBuilder
public void Build() {
System.Console.WriteLine("Building with Int32: " + BuildParameter);
}
// Implement from IBuilder<T>
public Int32 BuildParameter {get; private set;}
}
然后,您可以将任何IBuilder<T>
传递为IBuilder
public class Program {
public static void Main() {
SpecificBuilder builder = new SpecificBuilder(42);
// SpecificBuilder implements IBuilder<Int32>
// Build accepts any IBuilder
// So this is legal:
Build(builder);
}
//
// Note this method accepts anything that inherits from IBuilder
//
public static void Build(IBuilder builder) {
builder.Build();
// If you'd need access to the BuildParameter of IBuilder<T>
// then this pattern fails you here.
// Unless of course you want to check for types and cast
}
}
如前所述:一旦您需要访问实现IBuilder<T>
的类之外的泛型类型,您需要开始区分类型并相应地转换它们。不那么优雅。
但是你可以用这种方式设计很多东西并保持可扩展性。我提出这个问题,因为我已经使用这种模式自己实现了图像过滤器,并且使用这种设计模式可以很好地实现BuildCollagePattern
。