我会让代码进行讨论:
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
&gt;收集到IThingServiceInstance<IThing>
?
如何编译此代码?
答案 0 :(得分: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”符号)。
<强> EDIT2 强>
这是您的代码未编译的原因。正如所指出的那样,由于您的ThingServiceInstance<T>
公开了IThingRepository<T>
属性,因此它也必须是协变的:
public interface IThingRepository<out T> where T : class, IThing { }
如下所示,您的属性必须是get-only(请记住,您只能返回 T
或U<T>
的实例)。
答案 1 :(得分:1)
如果你声明两个接口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返回的类型不是“兼容的”。