[英]C# - Generic method calling method which returns concrete type?
假设您有一个采用通用类型的方法,例如一个枚举eType以及一个具体对象。 然后,该方法根据枚举类型确定要调用的方法。 每个被调用的私有方法都知道自己的返回类型(根据传入的对象的值实例化一个具体的类型化类)。 public方法事先不知道它将返回哪种类型。
/// A Generic method to call individual methods depending on the given enum
/// and returns a Generic type.
public T GetSomething<T>(enum eType, Model myClass) where T : class
{
// Do some common tasks here before calling the private methods
// ...
switch(eType)
{
case eType.A:
return GetMethodA<T>(myClass);
case eType.B:
return GetMethodB<T>(myClass);
}
}
/// A method that returns a ConcreteTypeA object
private T GetMethodA<T>(MyClass myClass)
{
ConcreteTypeA cta = new ConcreteTypeA();
cta.X = myClass.X;
//... etc.
return cta;
}
/// A method that returns a ConcreteTypeA object
private T GetMethodB<T>(MyClass myClass)
{
ConcreteTypeB ctb = new ConcreteTypeB();
ctb.Y = myClass.Y;
//... etc.
return ctb;
}
这是基于Factory模式的,而不是调用单个方法(将它们公开)的替代方法,因此可以在切换案例之前完成通用的准备工作。
Visual Studio说“无法将类型“ ConcreteTypeA”隐式转换为“ T”,这会导致协方差和协方差,但是我不确定这是否是工厂模式的错误版本。
主要思想是,GetSomething()除了通用类型外,不知道/不在乎返回类型(将要使用的位置必须知道他们想要返回的类型)。 私有方法(MethodA,B,...)在进行自定义对象创建时必须处理具体类型。 ConcreteTypeA和B不共享相同的接口或基类。
eType枚举用于标识要调用的方法(请参见“ 设计模式:抽象工厂与工厂方法” ),这在工厂中通常会执行。 通用类型T将返回已知类型而不是例如对象,因为具体的返回类型不实现接口或基类。
与简单工厂的主要区别在于,实际返回值“类型T”仅由调用者和私有方法知道。 GetSomething返回的对象没有通用的基础/接口,或者甚至不需要通用。 枚举eType类似于public static Position Get(int id)
http://www.dotnetperls.com/factory中的 public static Position Get(int id)
,它仅标识主要工厂方法应该执行的操作。
这是不好还是错误的方法? 我是否应该直接使用单个方法(似乎不完全遵循Factory模式)?
用法是在这里需要初始化不同的类。 仅公开各个方法并直接调用它们将很容易。 将所有内容放在单个方法调用中的原因是允许进行通用处理,因为它们都需要MyClass实例进行初始化。
好的,谢谢您的澄清评论,我想我明白您在这里尝试做什么。
首先,您想将T约束为ConcreteTypeA和ConcreteTypeB的基类(我们称之为BaseType)。
其次,您可能想要删除枚举并决定通过类型参数T来调用哪种方法(这将阻止调用GetSomething <TypeA>(eType.B,myClass)的人 )
第三,您不需要在MethodA和MethodB上键入参数,只需让它们返回其通用基类型即可。
/// A Generic method to call individual methods depending on the given enum
/// and returns a Generic type.
public T GetSomething<T>(Model myClass) where T : BaseType
{
// Do some common tasks here before calling the private methods
// ...
if(typeof(T) == typeof(ConcreteTypeA))
return (T)GetMethodA(myClass);
if(typeof(T) == typeof(ConcreteTypeB))
return (T)GetMethodB(myClass);
}
您可以改用GetMethodA(myClass)作为T。
如果必须使用枚举而不是type参数来决定,则必须删除泛型并返回安全类型的基类(或者接受该方法有时会在枚举不匹配时抛出InvalidCast) T)
解决此问题的最简单方法是使私有生成器方法非通用,并使它们返回对象。 然后, GetSomething
方法可以将返回值转换为给定的类型T
:
private object MethodA(MyClass myClass)
{
ConcreteTypeA cta = new ConcreteTypeA();
//...
return cta;
}
public T GetSomething<T>(enum eType, Model myClass) where T : class
{
switch(eType)
{
case Type.A: return (T)MethodA(myClass);
case Type.B: return (T)MethodB(myClass);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.