繁体   English   中英

泛型派生类型的泛型方法返回对象

[英]Generic method returning objects of generic derrived types

我在C#中的泛型方面有些挣扎。 考虑这段代码:

public interface A {};
public interface B : A {};
public interface C : A {};

public interface IMyInterface<in T> where T : A {};

public class FirstImpl<T> : IMyInterface<T> where T : B {};
public class SecondImpl<T> : IMyInterface<T> where T : C {};

现在我需要一些工厂,该工厂采用一种类型并返回正确的实现:

public IMyInterface<T> Create<T>() where T : A 
{
    if(typeof(T) is B) {
        return new FirstImpl<T>();
    }
    if(typeof(T) is C) {
        return new SecondImpl<T>();
    }
}

这在两个层面上都不起作用。 第一个是返回类型。 第二个是我不能将“ T”传递到第一个或第二个实现中,因为它们需要更具体的类型。 任何想法如何解决这个问题?

每当您使用通用类型或方法编写代码,并且该代码对通用类型参数进行某种测试时,您就做错了。 (恕我直言,不用说,反射会更糟。)泛型类型的全部要点是编写依赖于泛型类型的代码。

在您的示例中,更好的方法是这样的:

static IMyInterface<T> CreateB<T>() where T : B
{
    return new FirstImpl<T>();
}

static IMyInterface<T> CreateC<T>() where T : C
{
    return new SecondImpl<T>();
}

即编写不同的方法来处理每种情况。 如果基于约束的方法行得通,则调用者无论如何都要知道正在处理什么。 因此,仅使用不同的方法名称就不会有问题,每种方法名称都将在适当的情况下使用。

如果以上内容不能解决您的特定情况,请改进问题,使其包括一个良好的“ 最小,完整和可验证”代码示例 ,该示例不仅显示您尝试使用的泛型类型,还显示它们将在其中使用的上下文。用过的。

如果您不介意反思,可以这样做:

public static IMyInterface<T> Create<T>() where T : A 
{
    if (typeof(B).IsAssignableFrom(typeof(T)))
    {
        var type = typeof(FirstImpl<>);
        var boundType = type.MakeGenericType(typeof(T));
        return (IMyInterface<T>) Activator.CreateInstance(boundType);
    }
    else if(typeof(C).IsAssignableFrom(typeof(T)))
    {
        var type = typeof(SecondImpl<>);
        var boundType = type.MakeGenericType(typeof(T));
        return (IMyInterface<T>) Activator.CreateInstance(boundType);
    }

    throw new ArgumentException("unknown type " + typeof(T).Name);
}

您可以在.net小提琴中尝试

最简单的方法是仅使用Create<T>()方法添加额外的约束,例如public IMyInterface<T> Create<T>() where T : A , B, C如果想要保持设计完整public IMyInterface<T> Create<T>() where T : A , B, Cpublic IMyInterface<T> Create<T>() where T : A , B, C 对于默认情况,您可能需要一个实现来使方法完整。

public IMyInterface<T> Create<T>() where T : A, B, C
{
    if (typeof(T) is B)
    {
        return new FirstImpl<T>();
    }
    if (typeof(T) is C)
    {
        return new SecondImpl<T>();
    }
    return new DefaultImpl<T>;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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