using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
public abstract class Provider
{
public abstract string Name { get; }
}
public abstract class Provider<T> : Provider
where T : BaseService
{
public T Service { get; set; }
}
public class FooProvider : Provider<FooService>
{
public override string Name => "FooProvider";
}
public class BarProvider : Provider<BarService>
{
public override string Name => "BarProvider";
}
public abstract class BaseService
{
public abstract string Name { get; }
}
public class FooService : BaseService
{
public override string Name => "FooService";
}
public class BarService : BaseService
{
public override string Name => "BarService";
}
class Program
{
public static List<BaseService> Services = new List<BaseService> { };
public static List<Provider<BaseService>> Providers = new List<Provider<BaseService>> { };
static void Main()
{
Console.WriteLine("Services");
Services.Add(new FooService());
Services.Add(new BarService());
Services.ForEach(service => Console.WriteLine(service.Name));
Console.WriteLine("Provider");
// Error CS1503 Argument 1: cannot convert from 'ConsoleApp1.FooProvider' to 'ConsoleApp1.Provider<ConsoleApp1.BaseService>' ConsoleApp1 C:\Projetos\Git\sbh\src\ms\sbh - src - ms - migracao\ConsoleApp1\Program.cs 56 Active
Providers.Add(new FooProvider());
//Error CS1503 Argument 1: cannot convert from 'ConsoleApp1.BarProvider' to 'ConsoleApp1.Provider<ConsoleApp1.BaseService>' ConsoleApp1 C:\Projetos\Git\sbh\src\ms\sbh - src - ms - migracao\ConsoleApp1\Program.cs 61 Active
Providers.Add(new BarProvider());
Providers.ForEach(provider => Console.WriteLine($"provider {provider.Name} - service {provider.Service.Name}"));
}
}
}
If you comment the command to add provider you'll see that errors not happens. I don't know explain why error occurs by I know that simple list of Service working and list of Provider not working.
This happens because of covariance in generics. The services in your example work because List<T>
(or more precisely IEnumerable<T>
) is marked as having a covariant parameter type.
This allows a FooService to be used as BaseService. The generic in your Provider class is not marked with variance so it can't be used in the same way. If you want this functionality you need to create a variant generic interface.