C#泛型铸造(协方差和逆变?) [英] C# Casting generics (covariance and contravariance?)

查看:144
本文介绍了C#泛型铸造(协方差和逆变?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一些建议/在这方面的帮助,我不能看到木从树上了。

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆