简体   繁体   中英

C# : Downcasting Generic object with derived interfaces to the base interface

I have the following object architecture:

public interface IConfigAlarmBase{}
public interface IConfigAlarmBinary:IConfigAlarmBase{}
public interface IConfigAlarmRanged:IConfigAlarmBase{}
public interface IAlarmItem<TConfig> where TConfig : IConfigAlarmBase{}
public abstract class AlarmItemBase<TConfig> : IAlarmItem<TConfig> where TConfig :IConfigAlarmBase {}
public abstract class AlarmItemBinaryBase:AlarmItemBase<IConfigAlarmBinary>{}
public abstract class AlarmItemRangedBase<TConfig> : AlarmItemBase<TConfig> where TConfig:IConfigAlarmRanged{}
public class AlarmImplementation:AlarmItemRangedBase<IConfigAlarmRanged>

And then there are some implementations of the AlarmItemBinaryBase object and its brother the AlarmItemRangedBase .

I wanted to store all my alarms in a single list that would be defined as: List<IAlarmItem<IConfigAlarmBase>>

But when I instantiate my list and try to fill it I get an error:

System.InvalidCastException: Unable to cast object of type 'Alarm.Implementations.AlarmImplementation' to type 'Common.Application.Alarm.IAlarmItem`1[Common.Config.Alarms.IConfigAlarmBase]'.

Which I don't understand as the AlarmImplementation is an implementation of IAlarmItem (through the class hierarchy of the AlarmItemRangedBase ) and the IConfigAlarmRanged is a child of the IConfigAlarmBase . To me this was supposed to be a downcast as all the classes are derived from the Base one.

But it seems I'm wrong. Would it be possible that when the compiler replace the templates it then consider the generic type as specific type ignoring the relationships between the templated types?

Thanks for all the consideration you'll give to this question.

Your list is List<IAlarmItem<IConfigAlarmBase>> and you try to add an AlarmItemRangedBase<IConfigAlarmRanged> , so you have type mismatch even if IConfigAlarmRanged inherits from IConfigAlarmBase because IAlarmItem<IConfigAlarmBase> and IAlarmItem<IConfigAlarmRanged> are not the same type: they are two distinct closed constructed generic types and you can't cast from one to the other.

For example, List<string> and List<int> are distinct types, there is no hierarchy between and no side-casting is available.

Generics -Open and closed constructed Types

About the lack of true generic polymorphism and the missing diamond operator in C#

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