1

我有这个通用类

public abstract class BaseExportCommand<T> where T : EditableEntity, new()
{
....
}

我有这个派生类

public class MessageExportCommand : BaseExportCommand<Message> 
{
 .....
}

Message 继承自 EdittableEntity 的位置

public class Message : EditableEntity
{
...
}

现在,当我尝试做这个声明时

BaseExportCommand<EditableEntity> myValue = new MessageExportCommand ();

我收到以下错误:

Cannot convert type 'MessageExportCommand' to 'BaseExportCommand<EditableEntity>'   

知道为什么吗?

4

2 回答 2

8

知道为什么吗?

是的。您的泛型类型T.

我们不能立即判断它是否应该。例如,假设它看起来像这样:

public abstract class BaseExportCommand<T> where T : EditableEntity, new()
{
    public abstract DoSomethingWithEntity(T entity);
}

然后假设你可以写:

BaseExportCommand<EditableEntity> myValue = new MessageExportCommand();
EditableEntity entity = new SomeEditableEntity();
myValue.DoSomethingWithEntity(entity);

...而MessageExportCommand只期望DoSomethingWithEntity(Message).

如果您仅将T其用作 的输出,这是安全的BaseExportCommand<T>,但不幸的是,C# 不允许您为类声明协变类型参数 - 仅用于接口和委托。所以你可能写:

// Note the "out" part, signifying covariance
public interface IExportCommand<out T> where T : EditableEntity, new()

然后:

IExportCommand<EditableEntity> = new MessageExportCommand();

...但这取决于接口中声明了哪些成员。如果您尝试T在任何“输入”位置使用,编译器会注意到并阻止您进行T协变声明。

有关更多详细信息,请参阅MSDN 中的泛型类型的方差,以及Eric Lippert 的有关该主题的博客文章(安顿下来,放松一下,有很多要阅读的内容)。

于 2012-11-19T22:34:51.170 回答
1

这仅在您声明T为协变体时才有效:

public abstract class BaseExportCommand<out T> where T : EditableEntry, new()
{
    ...
}

协变意味着,您可以将它用于T或任何继承自T.

另请参阅协变和逆变常见问题解答

于 2012-11-19T22:33:28.837 回答