泛型不能转换类型

Generics cannot convert type

interface IComponent { /*code*/ }
interface IContent : IComponent { /*code*/ }
interface IMedia : IComponent { /*code*/ }
class A : IContent { /*code*/ }
class B : IMedia { /*code*/ }
class C : IContent, IMedia { /*code*/ }

private static T GetComponent<T>(string itemTemplate)
        where T : IComponent, new ()
{
    T component;
    switch (itemTemplate)
    {
        case "template_1":
            component = new A();
            break;
        case "template_2":
            component = new B();
            break;
        case "template_3":
            component = new C();
            break;
        default:
            throw new ArgumentOutOfRangeException("itemTemplate");
     }
     return component;
 }

我在创建派生类型的实例时遇到这些构建错误:

Cannot implicitly convert type 'Objects.A' to 'T'
Cannot implicitly convert type 'Objects.B' to 'T'
Cannot implicitly convert type 'Objects.C' to 'T'

编辑:itemTemplate 参数是 Sitecore 项目模板的名称。

您需要转换为 T - 但首先,有点烦人的是,由于 C# 中有关类型参数转换的规则,您需要转换为 object

虽然我个人会删除局部变量,但这对您没有帮助:

private static T GetComponent<T>(string condition)
        where T : IComponent, new ()
{
    switch (condition)
    {
        case "condition_1":
            return (T) (object) new A();
        case "condition_2":
            return (T) (object) new B();
        case "condition_3":
            return (T) (object) new C();
        default:
            throw new ArgumentException("condition");
     }
}

你真的应该考虑通用方法在这里是否合适......你真的比制作方法 return IComponent 并让调用者强制转换有什么好处吗?

基本上,不清楚条件与请求的类型有什么关系。

C# 编译器阻止的原因是您可以调用以下情况:

GetComponent<A>("condition_2");

此调用不会满足编译器的要求,因为 "condition_2" 将创建新的 B,而不是 A。

由于您只使用泛型类型 T 作为 return 类型,我建议您不要在这里使用泛型,只需遵循工厂模式即可:

private static IComponent GetComponent(string condition)
{
    IComponent component;
    switch (condition)
    {
        case "condition_1":
            component = new A();
            break;
        case "condition_2":
            component = new B();
            break;
        case "condition_3":
            component = new C();
            break;
        default:
            throw new ArgumentOutOfRangeException("condition");
    }
    return component;
}