Cannot implicitly convert MyType<Foo> to MyType<IFoo>
-
28-06-2021 - |
Question
I am not sure if this is a Covariance and Contravariance issue but I cannot get this working. Here is the code:
public interface IDto { }
public class PaginatedDto<TDto> where TDto : IDto {
public int PageIndex { get; set; }
public int PageSize { get; set; }
public int TotalCount { get; set; }
public int TotalPageCount { get; set; }
public bool HasNextPage { get; set; }
public bool HasPreviousPage { get; set; }
public IEnumerable<TDto> Dtos { get; set; }
}
public class PersonDto : IDto {
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public int Age { get; set; }
}
class Program {
static void Main(string[] args) {
var people = new List<PersonDto> {
new PersonDto { },
new PersonDto { },
new PersonDto { },
};
var paginatedPersonDto = new PaginatedDto<PersonDto>() {
Dtos = people
};
//ProcessDto doesn't accept this
ProcessDto(paginatedPersonDto);
}
private static void ProcessDto(PaginatedDto<IDto> paginatedDto) {
//Do work...
}
}
For some reason, I cannot pass PaginatedDto<PersonDto>
as PaginatedDto<IDto>
to ProcessDto
method. Any idea how can I solve this issue?
Solution
Yes this is a variance issue. You need to create an interface (only interfaces and delegates can be co/contravariant) IPaginatedDto<out TDto>
where the Dtos
cannot have a setter (otherwise you cannot use out
):
public interface IPaginatedDto<out TDto> where TDto : IDto
{
int PageIndex { get; set; }
int PageSize { get; set; }
int TotalCount { get; set; }
int TotalPageCount { get; set; }
bool HasNextPage { get; set; }
bool HasPreviousPage { get; set; }
IEnumerable<TDto> Dtos { get; }
}
And your PaginatedDto<TDto>
will implement this interface:
public class PaginatedDto<TDto> : IPaginatedDto<TDto> where TDto : IDto
{
public int PageIndex { get; set; }
public int PageSize { get; set; }
public int TotalCount { get; set; }
public int TotalPageCount { get; set; }
public bool HasNextPage { get; set; }
public bool HasPreviousPage { get; set; }
public IEnumerable<TDto> Dtos { get; set; }
}
And use the interface in your method:
private static void ProcessDto(IPaginatedDto<IDto> paginatedDto)
{
//Do work...
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow