问题
Why the property get the error while the method can be compiled?
public interface IFoo {}
public interface IBar<out T> where T : IFoo {}
public interface IItem<out T> where T: IFoo
{
// IEnumerable<IBar<T>> GetList(); // works
IEnumerable<IBar<T>> ItemList { get; set; } // Error!
}
Error:
Invalid variance: The type parameter 'T' must be contravariantly valid on 'UserQuery.IItem<T>.ItemList'. 'T' is covariant.
回答1:
You get the compiler error because you have a property getter (get) and a setter (set). The property getter has the T in it's output so out works, but the property setter will have the T in its input so it would need the in modifier.
Because you have out on T you need to remove the setter and it will compile:
public interface IItem<out T> where T : IFoo
{
// IEnumerable<IBar<T>> GetList(); // works
IEnumerable<IBar<T>> ItemList { get; } // also works
}
If your T is an in generic argument then the following would work:
public interface IItem<in T> where T : IFoo
{
IEnumerable<IBar<T>> ItemList { set; }
}
But you cannot have both (out,in) at the same time so you cannot have a co/contravariant property with a getter and a setter.
回答2:
The setter is not allowed, since if it were you would be able to do this:
public interface ISubFoo : IFoo { }
IItem<ISubFoo> item = //whatever
item.ItemList = new List<IBar<IFoo>>>();
which is not type safe.
来源:https://stackoverflow.com/questions/12484601/invalid-variance-the-type-parameter-t-must-be-contravariantly-valid-on-userq