c#类型转换泛型(协方差和逆变?)

本文关键字:方差 类型转换 泛型 | 更新日期: 2023-09-27 18:16:51

我需要一些建议/帮助,我再也看不到树木了

它是一系列使用泛型实现一些接口的直接类。

然后我试着转换具体类型,例如:

MyGenericObject<SomeObject> _obj;
IMyGenericObject<ISomeObject> _genObj = (IMyGenericObject<ISomeObject>)_obj;

//强制转换无效

我读过一些关于协方差和逆变的文章,但不太清楚为什么这是不可能的,或者如何绕过它?


那么,在这个例子中:

public interface IMyObject<in T> where T : IBaseObject
{
    T Activity { get; set; }
}

不工作…


…因为,你不能获取和设置Activity属性。

在这个例子中,我需要做:

public interface IMyObject<out T> where T : IBaseObject
    {
        T Activity { get; }
    }

希望能帮助到一些人,感谢所有的帮助!

c#类型转换泛型(协方差和逆变?)

只有在将接口声明为具有协变(out)参数时才能这样做。只有当参数被协变使用时,你才能这样做。

例如,如果接口IMyGenericObject<T>有一个接受T参数的方法,这将阻止您将参数声明为协变。相反,如果有一个返回T的方法,则可以阻止您将参数声明为逆变。

编辑

作为对SLaks的回答的回应,我很想重复Eric Lippert关于协逆变的所有文章。参见http://blogs.msdn.com/b/ericlippert/archive/tags/Covariance+and+Contravariance/以及他在SO中的回答(最近的一次是https://stackoverflow.com/a/8380213/385844)

总结:

不能将IList<string>强制转换为IList<object>,因为将FileInfo传递给IList<object>是合法的,但将其传递给IList<string>是不合法的。

您不能将IList<object>强制转换为IList<string>,因为从IList<string>中检索项并将其分配给字符串引用是合法的,但是IList<object>可能包含FileInfo,不能分配给字符串引用。

编辑2

既然你问了建议,也可以把接口分成协变部分和逆变部分。要继续列表示例,可以使用以下接口

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>
{
    //...
}

这允许您根据上下文协变或逆变地使用类。

您需要将接口声明为具有协变(out)泛型参数