无法将通用接口的具体实例添加到泛型集合中

Mar*_*son 5 c# oop generics

我会让代码说话:

using System.Collections.Generic;

namespace test
{
    public interface IThing { } // can't change this - it's a 3rd party thing

    public interface IThingRepository<T> where T : class, IThing { } // can't change this - it's a 3rd party thing

    public interface IThingServiceInstance<T>
      where T : class, IThing
    {
        IThingRepository<T> Repository { get; set; }
    }

    public class ThingServiceInstance<T> : IThingServiceInstance<T> where T : class, IThing
    {
        public IThingRepository<T> Repository { get; set; }

    }

    public class MyThing : IThing
    {
    }

    class Test
    {
        public void DoStuff()
        {
            IList<IThingServiceInstance<IThing>> thingServiceInstances = new List<IThingServiceInstance<IThing>>();
            // the following line does not compile. Errors are:
            // 1: The best overloaded method match for 'System.Collections.Generic.ICollection<test.IThingServiceInstance<test.IThing>>.Add(test.IThingServiceInstance<test.IThing>)' has some invalid arguments    C:\TFS\FACE\ResearchArea\ArgonServiceBusSpike\Argon_Service_Bus_Spike_v2\Argon.ServiceLayer\test.cs 31  13  Argon.ServiceGateway
            // 2: Argument 1: cannot convert from 'test.ThingServiceInstance<test.MyThing>' to 'test.IThingServiceInstance<test.IThing>'    C:\TFS\FACE\ResearchArea\ArgonServiceBusSpike\Argon_Service_Bus_Spike_v2\Argon.ServiceLayer\test.cs 31  39  Argon.ServiceGateway
            // Why? ThingServiceInstance is an IThingServiceInstance and MyThing is an IThing
            thingServiceInstances.Add(new ThingServiceInstance<MyThing>());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果ThingServiceInstanceIThingServiceInstanceMyThingIThing,为什么我不能添加一个ThingServiceInstance<MyThing>的集合IThingServiceInstance<IThing>

我该怎么做才能编译这段代码?

dca*_*tro 3

ThingServiceInstance<MyThing>不是子类型IThingServiceInstance<IMyThing>,因为其类型参数IThingServiceInstance<T>不变的<T>

如果你想创建 的ThingServiceInstance<MyThing>子类型IThingServiceInstance<IMyThing>,那么T必须是协变的。在 C# 中,您可以通过IThingServiceInstance<T>如下声明来做到这一点:

public interface IThingServiceInstance<out T>
Run Code Online (Sandbox Code Playgroud)

然而,编辑 这意味着ThingServiceInstance<T>只能返回 T 的实例,但永远不会将它们作为方法参数(因此是“out”符号)。

编辑2

这就是您的代码无法编译的原因。正如所指出的,由于您ThingServiceInstance<T>公开了一个IThingRepository<T>属性,因此它也必须是协变的,如下所示:

public interface IThingRepository<out T> where T : class, IThing { }
Run Code Online (Sandbox Code Playgroud)

如下所示,您的属性必须是仅获取的(请记住,您只能返回T, 或的实例U<T>)。