Кто-то может объяснить мне, почему происходит эта ошибка. Я попытался создать провайдера, чтобы передать список сервисов для установления соединения между obj1 и service1. - PullRequest
0 голосов
/ 15 апреля 2020
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}"));
        }
    }
}

Если вы прокомментируете команду добавления провайдера, вы увидите, что ошибок не происходит. Я не знаю, объясните, почему возникает ошибка: я знаю, что простой список Служб работает, а список Провайдеров не работает.

1 Ответ

0 голосов
/ 24 апреля 2020

Это происходит из-за ковариации в дженериках. Службы в вашем примере работают, потому что List<T> (или, точнее, IEnumerable<T>) помечен как имеющий ковариантный тип параметра.

https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance#list -of-option-generi c -интерфейс -and-Delegate-types

Это позволяет использовать FooService в качестве BaseService. Обобщение c в вашем классе провайдера не помечено как дисперсия, поэтому его нельзя использовать таким же образом. Если вы хотите эту функциональность, вам нужно создать вариант универсального интерфейса c.

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/covariance-contravariance/creating-variant-generic-interfaces

...