I'll attempt to shorten this code example:
public interface IThing
{
//... Stuff
}
public class Thing1 : IThing
{
}
public class Thing2 : IThing
{
}
public interface IThingView<out T>
{
ICollection<T> ViewAll();
}
public class ThingView<T> : IThingView<T>
{
ICollection<T> ViewAll() { return new List<T>(); } // There's a big operation here
}
public interface IThingViewerFactory
{
public IThingView<IThing> Build(string Which);
}
public class ThingViewerFactory
{
public IThingView<IThing> Build(string Which)
{
if(Which.Equals("Thing1") { return new (IThingView<IThing>)new ThingViewer<Thing1>();}
开发者_如何学编程 else { return new (IThingView<IThing>)new ThingViewer<Thing2>();}
}
}
That's a rough idea of what I'm doing. I have a number of Thing classes that require a viewer, which will follow a comon interface. I'd like a factory to generate these by me passing in a string with the name. I keep getting a compiler error complaining:
Invalid variance: The type parameter 'T' must be invariantly valid on 'IThingView.ViewAll()'. 'T' is covariant.
I realize even if I get this to work, I'll have to do some casting afterwards... I'm fine with that. And I realize this approach is more than likely not necessary. At this point this has become more of a pride/curiosity issue.
Thanks!
You cannot make a covariant ICollection<T>
, since it allows you to put T
s into it.
You can make a covariant read-only collection, a contravariant write-only collection, or an invariant read-write collection.
You can't do both, or it wouldn't be typesafe.
To expand on SLaks answer:
To make your code compile, change the return type of ViewAll
from ICollection<T>
to IEnumerable<T>
.
精彩评论