【问题标题】:Casting Generic type to base type将通用类型转换为基本类型
【发布时间】:2026-01-01 11:05:01
【问题描述】:

我有下一个场景:

public class RequestBase { }
public class ResponseBase { }

public interface IService<TRequest, TResponse>
           where TRequest : RequestBase where TResponse : ResponseBase
{
    TResponse Execute(TRequest request);
}

public class MyRequest : RequestBase { }
public class MyResponse : ResponseBase { }

public class MyService : IService<MyRequest, MyResponse>
{
    public MyResponse Execute(MyRequest request)
    {
        return new MyResponse();
    }
}

现在我正在创建将创建我的服务的工厂:

class ServicesFactory
{
    public IService<RequestBase, ResponseBase> Create()
    {
        var service = new MyService();
        return (IService<RequestBase, ResponseBase>)service;
    }    
}

问题是转换抛出异常。

如何将派生类型转换为基类型?

【问题讨论】:

  • 您可以为您使用的语言添加标签吗?可能是 C#?
  • 如果你通过基类来推动一切,那么没有理由使用泛型。如果您想要静态类型,请更改您的创建或工厂签名以包含类型参数。否则你也可以只使用对象或基本类型。
  • 这当然只是我的代码的一个简化示例,但我确实需要这个层次结构

标签: c# generics


【解决方案1】:

让你的接口在TResponse上协变:

public interface IService<TRequest, out TResponse>

您将能够将MyService 转换为IService&lt;MyRequest, ResponseBase&gt;。请注意,无法转换为IService&lt;RequestBase, ResponseBase&gt;,因为并非所有RequestBases 都是MyRequests。

也就是说,您可以使用不同的类来装饰MyService,该类将在运行时检查传入的RequestBase 是否实际上是MyRequest。如果接口需要任何RequestBase,这当然违反了 LSP。

【讨论】:

  • 我试过了,但没用。我还尝试向我的 RequestBase 和 ResponseBase 添加接口,然后转换为 IService 也没有用。在这两种情况下,我都会遇到异常无法将“Playground.MyService”类型的对象转换为“Playground.IService`2[Playground.RequestBase,Playground.ResponseBase]”。
  • out 关键字表示 co 方差(out 关键字在这里是正确的;接口确实是在 TResponse 上协变的),而不是逆变(即由in 关键字表示)。
  • @Kyle 对,我总是把他们弄糊涂。修复。
  • @eitanby 阅读其余答案:将MyService 转换为IService&lt;RequestBase, ResponseBase&gt; 是非法的,因为前者没有实现后者:你不能合法地调用myService.Execute(new AnotherClassThatInheritsFromRequest()) 可以合法地使用 IService&lt;RequestBase, ResponseBase&gt; 的实例进行