我有一Address节课:
public class Address
{
//Some stuff
}
Run Code Online (Sandbox Code Playgroud)
并且有一个相应的*Wrapper类来强制执行有关如何使用Address该类的某些规则:
public class AddressWrapper : IWrapped<Address>
{
private Address _wrapped;
public Address GetWrapped()
{
return _wrapped;
}
//And some more
}
Run Code Online (Sandbox Code Playgroud)
其中IWrapped定义为:
public interface IWrapped<T>
{
T GetWrapped();
}
Run Code Online (Sandbox Code Playgroud)
我有以下通用类来保存这些实体(还有其他实体遵循这种模式Entity和EntityWrapper):
public class GenericRepository
{
private GenericRepository() { }
public static void Add<T>(IWrapped<T> entity)
{
//Do something
}
public static void AddList<T>(IList<IWrapped<T>> entities)
{
//Do something
}
}
Run Code Online (Sandbox Code Playgroud)
我有这个测试代码:
[Test]
public void UseGenericRepository()
{
AddressWrapper addrW = new AddressWrapper();
addrW.AddrLine1 = "x";
addrW.AddrLine2 = "y";
addrW.AddrLine3 = "z";
addrW.City = "Starling City";
//This works as expected
GenericRepository.Add<Address>(addrW);
IList<AddressWrapper> addrList = new List<AddressWrapper>();
//Fill up the addrList
//This gives error: best overloaded method match has some invalid
//arguments
GenericRepository.AddList<Address>(addrList);
}
Run Code Online (Sandbox Code Playgroud)
AddressWrapped是类型IWrapped<Address>(即,它实现它)并且
Address是给予AddList方法的类型参数,因此类型应该排列.我知道这是由于我对C#泛型(熟悉Java泛型)的了解有限,但无法弄清楚这里有什么问题 - 它应该有用.
这可能没有任何区别,但这是我的配置:
这是因为缺少类型方差IList<T>.(IList<int>不是IList<object>).
使用IEnumerable<T>,因为它是协变的:
public static void AddList<T>(IEnumerable<IWrapped<T>> entities)
{
//Do something
}
Run Code Online (Sandbox Code Playgroud)
原因:如果你得到一个实例List<AddressWrapper>,编译器不知道它是否与任何可能的实现兼容IList<IWrapped<T>>.假设另一个实现的类IWrapped<T>.写入List时它不兼容.即使您没有写入列表AddList,编译器也只接受兼容类型.IEnumerable<T>不能写,所以它可以是变体.
与我建议在您自己的界面中使用协方差的问题无关:
public interface IWrapped<out T>
Run Code Online (Sandbox Code Playgroud)
与... IWrapped<Thing>兼容IWrapped<SpecificThing>.
MSDN:https://msdn.microsoft.com/en-us/library/ee207183.aspx