为什么这个泛型方法调用不匹配?

mar*_*gti 3 c# generics

我有一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)

我有以下通用类来保存这些实体(还有其他实体遵循这种模式EntityEntityWrapper):

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泛型)的了解有限,但无法弄清楚这里有什么问题 - 它应该有用.

这可能没有任何区别,但这是我的配置:

  • NHibernate 4.x
  • .NET Framework(4.5)

Ste*_*ger 5

这是因为缺少类型方差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