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



我会让代码说话:

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:TFSFACEResearchAreaArgonServiceBusSpikeArgon_Service_Bus_Spike_v2Argon.ServiceLayertest.cs 31  13  Argon.ServiceGateway
            // 2: Argument 1: cannot convert from 'test.ThingServiceInstance<test.MyThing>' to 'test.IThingServiceInstance<test.IThing>'    C:TFSFACEResearchAreaArgonServiceBusSpikeArgon_Service_Bus_Spike_v2Argon.ServiceLayertest.cs 31  39  Argon.ServiceGateway
            // Why? ThingServiceInstance is an IThingServiceInstance and MyThing is an IThing
            thingServiceInstances.Add(new ThingServiceInstance<MyThing>());
        }
    }
}

如果ThingServiceInstanceIThingServiceInstanceMyThingIThing,为什么我不能将ThingServiceInstance<MyThing>添加到IThingServiceInstance<IThing>集合中?

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

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

如果你想使ThingServiceInstance<MyThing>成为IThingServiceInstance<IMyThing>的子类型,那么T必须是协变的。在 C# 中,可以通过声明IThingServiceInstance<T>来实现:

public interface IThingServiceInstance<out T>

编辑然而,这意味着ThingServiceInstance<T>只能返回 T 的实例,但永远不能将它们作为方法参数(因此使用"out"表示法)。

编辑2

这就是代码未编译的要点。如前所述,由于您的ThingServiceInstance<T>公开了一个IThingRepository<T>属性,因此它也必须是协变的,如下所示:

public interface IThingRepository<out T> where T : class, IThing { }

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

如果你声明了两个接口 coariant,并从 IThingServiceInstance 中删除 setter ,你可以让它编译。

当然,您无法更改第三方界面,因此这并没有真正的帮助。

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

如果IThingRepository<T>没有声明T协变,则

T : A

你没有得到

IThingRepository<T> : IThingRespository<A>

所以你不能有

IThingServiceInstance<T> : IThingServiceInstance<A>

因为 getter 返回的类型不"兼容"。

最新更新