繁体   English   中英

C#-返回具体类型的泛型方法调用方法?

[英]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;
}
  • eType =确定要调用的方法
  • T =通用返回类型
  • GetSomething():除了扩展类之外,对返回类型一无所知。
  • GetMethodA():获取一个MyClass对象,初始化,填充,返回ConcreteTypeA

这是基于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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM