I need some advice/help on this, I can’t see the wood from the trees any more.
It’s a straight forward series of classes implementing some interfaces using generics.
Then I’m trying to cast the concrete types for example:
MyGenericObject<SomeObject> _obj;
IMyGenericObject<ISomeObject> _genObj = (IMyGenericObject<ISomeObject>)_obj;
// Invalid cast
I’ve read some articles about covariance and contravariance but not too clear why this wouldn’t be possible, or how to get round it?
So, in this example:
public interface IMyObject<in T> where T : IBaseObject
{
T Activity { get; set; }
}
wouldn’t work…
….because, you can’t get and set the Activity property.
In this example, I needed to do:
public interface IMyObject<out T> where T : IBaseObject
{
T Activity { get; }
}
hope that helps someone, and thanks to all for help!
You can only do that if you declare the interface as having a covariant (
out) parameter. You can only do that if the parameter is used covariantly.For example, if the interface
IMyGenericObject<T>has a method taking aTparameter, this prevents you from declaring the parameter as covariant. Conversely, if there is a method that returns aT, that prevents you from declaring the parameter as contravariant.EDIT
In response to your comment on SLaks’s answer, I’m tempted to repeat everything Eric Lippert has ever written on co- and contravariance. See http://blogs.msdn.com/b/ericlippert/archive/tags/Covariance+and+Contravariance/ and also his answers in SO (most recently https://stackoverflow.com/a/8380213/385844)
To summarize:
You can’t cast
IList<string>toIList<object>because it’s legal to pass aFileInfoto anIList<object>, but it is not legal to pass it to anIList<string>.You can’t cast an
IList<object>to anIList<string>, because it’s legal to retrieve an item from anIList<string>and assign it to a string reference, but anIList<object>might contain a FileInfo, which can’t be assigned to a string reference.EDIT 2
Since you asked for advice, it’s also possible to split your interfaces into co- and contravariant parts. To continue with the list example, you could have these interfaces
This allows you to use the class covariantly or contravariantly, depending on the context.