如何将 object1 转换为 object1 的接口的接口

本文关键字:接口 object2 object1 转换 | 更新日期: 2023-09-27 18:34:27

假设我有这样的安排:

    public interface ICreatable
    {
        int CreatedByUserId { get; set; }
    }
    public class Unicorn : ICreatable
    {
        public int CreatedByUserId { get; set; }
    }
    public interface ICrudService<T>
        where T : class, ICreatable
    {
        T DoSomething(T t);
    }
    public class UnicornService : ICrudService<Unicorn>
    {
        public Unicorn DoSomething(Unicorn unicorn)
        {
            var createdByUserId = unicorn.CreatedByUserId;
            // ...
            return unicorn;
        }
    }

并像这样使用它:

    static void Main(string[] args)
    {
        var unicorn = new Unicorn();
        var unicornService = new UnicornService();
        unicornService.DoSomething(unicorn);
    }

这运行良好。但是,假设我想将unicornService转换为ICrudService的接口类型以及它的通用类型,如下所示的接口类型:

        var crudService = unicornService as ICrudService<ICreatable>;

我遇到了问题。这是它的外观:

unicornService as ICrudService<Unicorn> --> casts is fine
unicornService as ICrudService<ICreatable> --> casts to null

似乎既然Unicorn源于ICreatable,而且既然ICrudService<T> where T: class, ICreatable,解决这个问题应该没有问题。我的搜索开始引导我进入协方差和逆变,但我在这个层面上迷失了方向。

如何将crudService投射到ICrudService<ICreatable>

更新:

使用协方差如下:

    public interface ICrudService<out T>

然后让智能感知说"无效方差:类型参数'T'在'ICrudService.DoSomething(T)'上必须逆变有效。T' 是协变的。这是如何工作的?

如何将 object1<object2> 转换为 object1 的接口<object2>的接口

ICrudService<Unicorn>不能被视为ICrudService<ICreatable>

ICrudService<Unicorn>对象只允许接受Unicorn类型的参数或Unicorn的子类型,但ICrudService<ICreatable>可以接受SomeOtherTypeOfICreatable的参数。

UnicornService类型被允许使用特定于Unicorn的成员,而不仅仅是ICreatable,因为这是它限制其函数的类型。 该限制禁止它满足更通用接口的 API。

所以,简而言之,这是不可能的。

你应该将 DoSomething 更改为接受 ICreatable,而不是 T 以使用 T 修饰符:

public interface ICrudService<out T>
    where T : class, ICreatable
{
    T DoSomething(ICreatable t);
}
public class UnicornService : ICrudService<Unicorn>
{
    public Unicorn DoSomething(ICreatable t)
    {
        var unicorn = (Unicorn)t;
        var createdByUserId = unicorn.CreatedByUserId; // or t.CreatedByUserId
        // ...
        return unicorn;
    }
}
请注意,如果非独角兽

将被传递给独角兽服务,则此代码将引发异常。