C
C#16mo ago
sp00ktober

❔ nested generic interface throws cast exception when added to list

Im working on a mod project and for this i need to handle different updates which are represented by individual classes that all inherit from the same generic interfaces. To accomplish the handling i also wrote a generic interface which can then be implemented by a class that should handle one specific class. In the end i want to have a list of handlers over which i can iterate to process the updates. This is my interface signature
internal interface IComponentUpdateHandler<T, H, C> where T : IComponentMetaclass where H : IComponentUpdate<T> where C : IComponentData<T>
internal interface IComponentUpdateHandler<T, H, C> where T : IComponentMetaclass where H : IComponentUpdate<T> where C : IComponentData<T>
These are the interfaces for the update and data interfaces
public interface IComponentUpdate<C> where C : IComponentMetaclass
public interface IComponentData<C> where C : IComponentMetaclass
public interface IComponentUpdate<C> where C : IComponentMetaclass
public interface IComponentData<C> where C : IComponentMetaclass
This is the signature of one of my handler classes
internal class InventoryModificationState_Handler : IComponentUpdateHandler<InventoryModificationState, InventoryModificationState.Update, InventoryModificationState.Data>
internal class InventoryModificationState_Handler : IComponentUpdateHandler<InventoryModificationState, InventoryModificationState.Update, InventoryModificationState.Data>
These are the signatures of the update and data classes
public class Update : IComponentUpdate<InventoryModificationState>
public class Data : IComponentData<InventoryModificationState>
public class Update : IComponentUpdate<InventoryModificationState>
public class Data : IComponentData<InventoryModificationState>
This is the signature of the base class
public class InventoryModificationState : IComponentMetaclass, IComponentFactory
public class InventoryModificationState : IComponentMetaclass, IComponentFactory
This is how i create the List and fill it with values
private List<IComponentUpdateHandler<IComponentMetaclass, IComponentUpdate<IComponentMetaclass>, IComponentData<IComponentMetaclass>>> handler { get; set; }
private ComponentUpdateManager()
{
handler = new List<IComponentUpdateHandler<IComponentMetaclass, IComponentUpdate<IComponentMetaclass>, IComponentData<IComponentMetaclass>>>
{
new InventoryModificationState_Handler(),
new PlayerCraftingInteractionState_Handler()
};
}
private List<IComponentUpdateHandler<IComponentMetaclass, IComponentUpdate<IComponentMetaclass>, IComponentData<IComponentMetaclass>>> handler { get; set; }
private ComponentUpdateManager()
{
handler = new List<IComponentUpdateHandler<IComponentMetaclass, IComponentUpdate<IComponentMetaclass>, IComponentData<IComponentMetaclass>>>
{
new InventoryModificationState_Handler(),
new PlayerCraftingInteractionState_Handler()
};
}
Im happy for any input as im stuck on this for some hours now 😄
18 Replies
Anton
Anton16mo ago
Covariance and Contravariance (C#)
Learn about covariance and contravariance and how they affect assignment compatibility. See a code example that demonstrates the differences between them.
sp00ktober
sp00ktober16mo ago
maybe you can elaborate a bit more on this? i've read through the article (and the linked one about interfaces) but this give me even more the feeling that i am doing things correctly here. tho something must be off and im just not seeing it
Anton
Anton16mo ago
InventoryModificationState_Handler does not implement IComponentUpdateHandler<IComponentMetaclass, IComponentUpdate<IComponentMetaclass>, IComponentData<IComponentMetaclass>>, because the type arguments there are not marked out (or in, I can't imagine this in my head, try both) Same thing with the other interfaces With the C : IMetaclass
sp00ktober
sp00ktober16mo ago
i have nearly no control over the Update and Data classes as well as the InventoryModificationState class and the IComponentXXXX interfaces. as i wrote this is part of a modding project and i need to work with these, so i hope its possible to solve this without modifying those mentioned interfaces/classes. gonne look at the in/out part you mentioned, never actually used it
Anton
Anton16mo ago
you just need to modify the interfaces you can't make this list without those modifications
sp00ktober
sp00ktober16mo ago
just in this case means some more complicated patches for me which will potentially break the whole game that this mod project is about, so if it is really required to do this then im afraid i need to find another way to implement similar functionality :/ would have been too good 😅
sp00ktober
sp00ktober16mo ago
just out of interest, im not really understanding why this is the case? i mean when i start to write a class that implements an interface its completely red at the beginning because it misses many things that are required because of the interface, but my ide (vs) does not say anything. just from looking at the implemented class it looks like it would implement the interface, see the image as a shorter handler example.
Anton
Anton16mo ago
No it doesn't Read the link I sent you more carefully
Anton
Anton16mo ago
It implements this interface
Anton
Anton16mo ago
that only
sp00ktober
sp00ktober16mo ago
in does not seem to change anything, out on the other hand tells me The parameter "H" must be contraviniant and valid for "IComponentUpdateHandler<T, H, C>.HandleUpdate(ENetPeerHandle, long, H, C)" "H" is covariant.
Anton
Anton16mo ago
That method means it can't be out
sp00ktober
sp00ktober16mo ago
aah well
Anton
Anton16mo ago
You can't implement that like you're trying to, fundamentally, at least not in a type-safe way
sp00ktober
sp00ktober16mo ago
ye thought so, i'll probably go in a type unsafe way then. still better than patching the games own interface structure and hope for the best
Anton
Anton16mo ago
No I mean you can't, even if you do patch them You'll have to cast the arguments You can wrap it into some delegates or an object that just casts the arguments in the methods Or implement both in your classes, the interface version that your list expects, the implementation of which would cast the arguments, and your own (but it then kinda loses its value)
sp00ktober
sp00ktober16mo ago
thanks for your input, really helped me! 😄
Accord
Accord16mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.