在 CS0535 中隐藏具体类型结果后面的泛型类型参数

问题描述 投票:0回答:1

我有一个相当学术的问题:为什么技术上不可能使用以下代码?

// abstractions
public record MappingRequest<TContract, TEntity>(TContract Contract, TEntity Entity);

public interface IMapper<TResult, TContract, TEntity>
{
    TResult Map(MappingRequest<TContract, TEntity> request);
}

// more readable abstraction
public interface ILocationMapper : IMapper<LocationResult, LocationContract, LocationEntity>
{
}

// concrete
public record LocationResult;
public record LocationContract;
public record LocationEntity;

public record LocationRequest(LocationContract Contract, LocationEntity Entity) : MappingRequest<LocationContract, LocationEntity>(Contract, Entity);

public class LocationMapper : ILocationMapper
{
    public LocationResult Map(LocationRequest request)
    {
        return new LocationResult();
    }
}

这给了我以下编译器错误:

Error CS0535 : 'LocationMapper' does not implement interface member 'IMapper<LocationResult, LocationContract, LocationEntity>.Map(MappingRequest<LocationContract, LocationEntity>)'

为什么编译器不能“推断”(不完全确定这是否是正确的术语)

LocationRequest
继承自
MappingRequest

谢谢你的解释🙏🏻

c# generics inheritance polymorphism
1个回答
0
投票

您的

LocationMapper.Map
方法当前接受
LocationRequest
,但
IMapper<LocationResult, LocationContract, LocationEntity>
的任何实现都必须实现接受
any
Map(而不仅仅是
MappingRequest<TContract, TEntity>
)的
LocationRequest
方法。

你的代码很简单,但想象一下

LocationRequest
有一个属性
Foo
:

public record LocationRequest(LocationContract Contract, LocationEntity Entity)
    : MappingRequest<LocationContract, LocationEntity>(Contract, Entity)
{
    public string Foo { get; }
}

你的方法尝试使用该属性:

public class LocationMapper : ILocationMapper
{
    public LocationResult Map(LocationRequest request)
    {
        Console.WriteLine(request.Foo);
        return new LocationResult();
    }
}

现在,如果您尝试将其称为

IMapper<LocationResult, LocationContract, LocationEntity>
,并使用另一个
MappingRequest<TContract, TEntity>
,我们就会遇到问题,因为没有 foo 属性。

例如

var request = new MappingRequest<TContract, TEntity>(default, default);
IMapper<LocationResult, LocationContract, LocationEntity> mapper = new LocationMapper();
mapper.Map(request); // We don't have any Foo to use !!

问题在于

LocationRequest
不是
MappingRequest<LocationContract, LocationEntity>
的简化别名,它是完全不同的类型。

如果冗长对您来说是个问题,那么您可以像这样为您的类型添加别名:

using LocationRequest = MappingRequest<LocationContract, LocationEntity>;
© www.soinside.com 2019 - 2024. All rights reserved.