简体   繁体   English

泛型转换

[英]Generic casting

I have this generic class 我有这个普通班

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

and I have this derived class 我有这个派生类

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

Where Message inherits from EdittableEntity 消息从EdittableEntity继承的地方

public class Message : EditableEntity
{
...
}

Now, when I try to do this statement 现在,当我尝试执行此语句时

BaseExportCommand<EditableEntity> myValue = new MessageExportCommand ();

I got the following error: 我收到以下错误:

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

Any idea why? 知道为什么吗?

Any idea why? 知道为什么吗?

Yes. 是。 Your generic type isn't covariant in T . 您的通用类型在T不是协变的。

We can't tell immediately whether it should be or not. 我们无法立即判断是否应该这样做。 For example, suppose it looked like this: 例如,假设它看起来像这样:

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

Then suppose you could write: 然后假设您可以编写:

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

... whereas MessageExportCommand only expects DoSomethingWithEntity(Message) . ...而MessageExportCommand只需要DoSomethingWithEntity(Message)

It's safe if you're only using T as an output from BaseExportCommand<T> , but unfortunately C# doesn't let you declare covariant type parameters for classes - only for interfaces and delegates. 如果仅将T用作BaseExportCommand<T>输出是安全的,但是不幸的是C#不允许您为类声明协变类型参数-仅针对接口和委托。 So you could potentially write: 因此,您可能写:

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

Then: 然后:

IExportCommand<EditableEntity> = new MessageExportCommand();

... but it depends on what members were declared in the interface. ...但是这取决于在接口中声明了哪些成员。 If you try to use T in any "input" positions, the compiler will notice and prevent you from declaring T covariantly. 如果尝试在任何“输入”位置使用T ,则编译器会注意到并阻止您协变地声明T

See Variance in Generic Types in MSDN for more details, as well as Eric Lippert's blog posts on the topic (settle back and relax, there's a lot to read). 有关更多详细信息,请参见MSDN中的“泛型类型”中的Variance ,以及有关该主题的Eric Lippert的博客文章 (安顿下来,放松一下,有很多书要读)。

This will only work if you declare T as co-variant: 仅当您将T声明为协变量时,这才有效:

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

Co-variant means, that you can use it for T or any class that inherits from T . 协变意味着,您可以将其用于T或从T继承的任何类。

Also see the Covariance and Contravariance FAQ . 另请参阅协方差和协方差常见问题解答

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM