C#接口作为参数类型转换问题

时间:2011-06-13 23:51:07

标签: c# inheritance interface

我有这种方法......

public static IList<IOutgoingMessage> CompressMessages(IList<IOutgoingMessageWithUserAndPtMedInfo> msgs)
    {
        StoreOriginalMessages(msgs);
        ...
    }

调用此方法......

 private static void StoreOriginalMessages(IList<IOutgoingMessage> msgs) {...}

IOutgoingMessageWithUserAndPtMedInfo定义如下......

public interface IOutgoingMessageWithUserAndPtMedInfo: IOutgoingMessage
{
    IPatientMedication PatientMedication { get; set; }
    IUserContainer User{ get; set; }
}

当我尝试从StoreOriginalMessages方法拨打CompressMessages时出现此错误:

无法从'System.Collections.Generic.IList <MyMediHealth.DataAccess.Containers.IOutgoingMessageWithUserAndPtMedInfo>'转换为'System.Collections.Generic.IList <MyMediHealth.DataAccess.Containers.IOutgoingMessage>'

不明白为什么。我希望它会接受它,因为IOutgoingMessageWithUserAndPtMedInfo继承自IOutgoingMessage

我做错了什么?

2 个答案:

答案 0 :(得分:5)

参考:Covariance and Contravariance in Generics

假设有以下2个接口和2个类:

interface IBase {}
interface IDerived : IBase {}

class Base {}
class Derived : Base {}

如果你这样做,你将得到相同的投射错误:

IList<IDerived> lid = null;
IList<IBase> lib = lid; //cannot cast IList<IDerived> to IList<IBase>

IList<Derived> ld = null;
IList<Base> lb = ld; //cannot cast IList<Derived> to IList<Base>

但是,以下内容编译得很好,因为IEnumerable<T>是为协方差声明的,其中IList<T>不是。{1}}。 IEnumerable<T>实际上是IEnumerable<out T>,表示type参数仅用于返回值,并且可以允许协方差。

IEnumerable<IDerived> lid = null;
IEnumerable<IBase> lib = lid;

IEnumerable<Derived> ld = null;
IEnumerable<Base> lb = ld;

答案 1 :(得分:3)

从你的方法的名称我得出结论,StoreOriginalMessages没有在列表中插入新元素?

你可以用

替换它
private static void StoreOriginalMessages(IEnumerable<IOutgoingMessage> msgs)

它应该能够顺利运行(如果你有C#4.0 - 在不幸的是没有协方差支持之前)。

如果您使用C#3.5,则还需要更改呼叫站点:

StoreOriginalMessages(msgs.Cast<IOutgoingMessage>());