I've a rather academic question: why is it technically not possible to use the following code?
// 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();
}
}
This gives me the following compiler error:
Error CS0535 : 'LocationMapper' does not implement interface member 'IMapper<LocationResult, LocationContract, LocationEntity>.Map(MappingRequest<LocationContract, LocationEntity>)'
Why can't the compiler not "infer" (not entirely sure whether this is the correct term here) that LocationRequest
inherits from MappingRequest
?
Your LocationMapper.Map
method currently accepts a LocationRequest
, but any implementation of IMapper<LocationResult, LocationContract, LocationEntity>
must implement a Map
method that accepts any MappingRequest<TContract, TEntity>
, not just LocationRequest
.
Your code is simple, but imagine LocationRequest
had a property Foo
:
public record LocationRequest(LocationContract Contract, LocationEntity Entity)
: MappingRequest<LocationContract, LocationEntity>(Contract, Entity)
{
public string Foo { get; }
}
And your method tried to use that property:
public class LocationMapper : ILocationMapper
{
public LocationResult Map(LocationRequest request)
{
Console.WriteLine(request.Foo);
return new LocationResult();
}
}
Now, if you try to call that as an IMapper<LocationResult, LocationContract, LocationEntity>
, with another MappingRequest<TContract, TEntity>
, we have a problem, because there is no Foo
property.
e.g.
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 !!
The problem is that LocationRequest
isn't a simplified alias for MappingRequest<LocationContract, LocationEntity>
, it's a completely different type altogether.
If verbosity is a problem for you, then you can alias your type like this:
using LocationRequest = MappingRequest<LocationContract, LocationEntity>;