C# 返回泛型驱动类型的对象的泛型方法

C# 返回泛型驱动类型的对象的泛型方法,c#,generics,C#,Generics,我在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 SecondIm

我在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 {};
公共接口A{};
公共接口B:A{};
公共接口C:A{};
公共接口IMyInterface,其中T:A{};
公共类FirstImpl:IMyInterface,其中T:B{};
公共类SecondImpl:IMyInterface,其中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>();
    }
}
public IMyInterface Create(),其中T:A
{
如果(T的类型为B){
返回新的FirstImpl();
}
如果(T的类型为C){
返回新的SecondImpl();
}
}

这在两个层面上都不起作用。第一种是返回类型。第二个问题是,我不能将“t”传递到第一个或第二个实现中,因为它们需要更具体的类型。你知道怎么解决这个问题吗

最短的方法是使用
Create()
方法添加额外的约束,如
public IMyInterface Create(),其中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>;
}
public IMyInterface Create(),其中T:A,B,C
{
如果(T的类型为B)
{
返回新的FirstImpl();
}
如果(T的类型为C)
{
返回新的SecondImpl();
}
返回新的DefaultImpl;
}

最短的方法是使用
Create()
方法添加额外的约束,如
public IMyInterface Create(),其中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>;
}
public IMyInterface Create(),其中T:A,B,C
{
如果(T的类型为B)
{
返回新的FirstImpl();
}
如果(T的类型为C)
{
返回新的SecondImpl();
}
返回新的DefaultImpl;
}

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

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);
}
publicstaticimyinterface Create(),其中T:A
{
if(typeof(B).可从(typeof(T))中识别)
{
变量类型=类型(第一个impl);
var boundType=type.MakeGenericType(typeof(T));
return(IMyInterface)Activator.CreateInstance(boundType);
}
else if(typeof(C).IsAssignableFrom(typeof(T)))
{
变量类型=类型化(第二个impl);
var boundType=type.MakeGenericType(typeof(T));
return(IMyInterface)Activator.CreateInstance(boundType);
}
抛出新ArgumentException(“未知类型”+typeof(T).Name);
}

您可以在一个

中尝试,如果您不介意反射,您可以这样做:

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);
}
publicstaticimyinterface Create(),其中T:A
{
if(typeof(B).可从(typeof(T))中识别)
{
变量类型=类型(第一个impl);
var boundType=type.MakeGenericType(typeof(T));
return(IMyInterface)Activator.CreateInstance(boundType);
}
else if(typeof(C).IsAssignableFrom(typeof(T)))
{
变量类型=类型化(第二个impl);
var boundType=type.MakeGenericType(typeof(T));
return(IMyInterface)Activator.CreateInstance(boundType);
}
抛出新ArgumentException(“未知类型”+typeof(T).Name);
}

只要有使用泛型类型或方法的代码,并且该代码对泛型类型参数进行了某种类型的测试,您就可以在一个

中尝试。(毫无疑问,陷入反射会更糟。)泛型类型的关键在于编写不依赖于泛型类型的代码

在您的示例中,更好的方法如下:

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

static IMyInterface<T> CreateC<T>() where T : C
{
    return new SecondImpl<T>();
}
static IMyInterface CreateB(),其中T:B
{
返回新的FirstImpl();
}
静态IMyInterface CreateC(),其中T:C
{
返回新的SecondImpl();
}
也就是说,编写不同的方法来处理每个场景。如果基于约束的方法能够奏效,调用方无论如何都必须知道它正在处理什么。因此,只要有不同的方法名就可以了,每个方法名都可以在相应的情况下使用


如果上述内容没有针对您的特定场景,请改进问题,使其包括一个良好的示例,不仅显示您尝试使用的泛型类型,还显示它们将在其中使用的上下文。

任何时候您有使用泛型类型或方法的代码,这段代码对泛型类型参数进行了某种测试,但您做得不对。(毫无疑问,陷入反射会更糟。)泛型类型的关键在于编写不依赖于泛型类型的代码

在您的示例中,更好的方法如下:

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

static IMyInterface<T> CreateC<T>() where T : C
{
    return new SecondImpl<T>();
}
static IMyInterface CreateB(),其中T:B
{
返回新的FirstImpl();
}
静态IMyInterface CreateC(),其中T:C
{
返回新的SecondImpl();
}
也就是说,编写不同的方法来处理每个场景。如果基于约束的方法能够奏效,调用方无论如何都必须知道它正在处理什么。因此,只要有不同的方法名就可以了,每个方法名都可以在相应的情况下使用


如果上述内容没有针对您的特定场景,请改进问题,使其包含一个好的内容,不仅显示您尝试使用的泛型类型,还显示它们将在其中使用的上下文。

,问题是,从技术上讲,在调用
new FirstImpl()时,您无法让编译器相信泛型类型t实际上是B或B的派生类型。有趣。值得深思。让我看看。你遗漏了几个新的关键字了吗?要理解这个问题已经够难了,不必处理那些即使满足您的要求也无法编译的代码。您是否打算编写
返回新的FirstImpl()
返回新的SecondImpl()?嗯,问题出在哪里