5

我会让代码说话:

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>());
        }
    }
}

如果ThingServiceInstance是一个IThingServiceInstance并且MyThing是一个IThing,为什么我不能将ThingServiceInstance<MyThing> 添加到一个集合中IThingServiceInstance<IThing>

我能做些什么来编译这段代码?

4

2 回答 2

3

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 { }

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

于 2013-11-14T14:13:30.653 回答
1

如果您声明两个接口 coariant 并从IThingServiceInstance.

当然,您不能更改第三方接口,所以这并没有真正的帮助。

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 返回的类型不是“兼容的”。

于 2013-11-14T14:15:14.740 回答