简体   繁体   中英

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

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 .

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) .

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. 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.

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).

This will only work if you declare T as co-variant:

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 .

Also see the Covariance and Contravariance FAQ .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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