C#泛型铸造(协方差和逆变?) [英] C# Casting generics (covariance and contravariance?)
问题描述
我需要一些建议/在这方面的帮助,我不能看到木从树上了。
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?
所以,在这个例子中:
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.
例如,如果接口 IMyGenericObject&LT; T&GT;
有服用 T
参数的方法,这prevents你声明参数作为协变。相反,如果有,返回的方法的 T
,即prevents你声明参数作为逆变。
For example, if the interface IMyGenericObject<T>
has a method taking a T
parameter, this prevents you from declaring the parameter as covariant. Conversely, if there is a method that returns a T
, that prevents you from declaring the parameter as contravariant.
修改
在回答关于SLaks的回答您的意见,我很想重复一切埃里克利珀曾经写了合作和逆变。请参阅<一href="http://blogs.msdn.com/b/ericlippert/archive/tags/Covariance+and+Contravariance/">http://blogs.msdn.com/b/ericlippert/archive/tags/Covariance+and+Contravariance/也是自己的答案,在SO(最近 http://stackoverflow.com/a/8380213/385844 )
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 http://stackoverflow.com/a/8380213/385844)
要总结一下:
您无法施展的IList&LT;字符串&GT;
到的IList&LT;对象&gt;
,因为它是合法的传递的FileInfo
到的IList&LT;对象&gt;
,但它是不合法的将它传递给一个的IList&LT ;字符串&GT;
You can't cast IList<string>
to IList<object>
because it's legal to pass a FileInfo
to an IList<object>
, but it is not legal to pass it to an IList<string>
.
您不能施放一个的IList&LT;对象&gt;
到的IList&LT;字符串&GT;
,因为它是合法的字符串&GT;从的IList&LT检索项目
并将其分配给一个字符串引用,但一个的IList&LT;对象&gt;
可能含有一个FileInfo,这是不能被分配给一个字符串引用
You can't cast an IList<object>
to an IList<string>
, because it's legal to retrieve an item from an IList<string>
and assign it to a string reference, but an IList<object>
might contain a FileInfo, which can't be assigned to a string reference.
编辑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
public interface ICovariantList<out T>
{
T this[int index] { get; }
//...
}
public interface IContravariantList<in T>
{
T this[int index] { set; }
void Add(T item);
//...
}
public class SomeList<T> : ICovariantList<T>, IContravariantList<T>
{
//...
}
这可以让你使用类协变或contravariantly,要看具体情况。
This allows you to use the class covariantly or contravariantly, depending on the context.
这篇关于C#泛型铸造(协方差和逆变?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!