简体   繁体   中英

Inheritance of nested generics / nested generics in abstract class C#

I have two abstract classes that can be inherited for explicit usage: A_GUI_Info and A_Info_Data. The GUI_Infos are GUI elements that display data. The Info_Datas are data classes, that transfer specific data to the according GUI_Info.

I want to express the dependency that an explicit GUI_Info has one explicit Info_Data through generics and still allow an inheritance. With other words, I want to avoid that a wrong explicit Info_Data is fed to an explicit GUI_Info. For example, I feed HUD_Info_Data to a Wrist_GUI_Element that does not have the means to represent it. > A kind of type-safety for inherited generics

Example:

class HUDInfoData : A_Info_Data
class HUDInfo<HUDInfoData > : A_GUI_Info<A_Info_Data> 
// but the generic cant be inherited like that

class HUDInfo : A_GUI_Info<A_Info_Data>
// doesnt define dependency

class HUDInfo : A_GUI_Info<HUDInfoData >
// also not working

Another approach is restrictions by where T : A_GUI_Info<D> where D : A_Info_Data But it did not work like that.

The final requirement, that I cant get to work is: I have an instance of the explicit Info and want to handle it in a function, that could also handle all other inherited Infos with their according Datas.

public HUD_Info<HUD_Info_Data> obj;

public List<A_GUI_Info<A_Info_Data>> infos;

public void SetConnection(string ID, A_GUI_Info<A_Info_Data> p)
{
    infos.Add(p);
}

It may end up that you need to use this kind of data structure:

public abstract class A_GUI_Info<G, D>
    where G : A_Info_Data<G, D>
    where D : A_GUI_Info<G, D>
{
    public G Gui { get; set; }
}

public abstract class A_Info_Data<G, D>
    where G : A_Info_Data<G, D>
    where D : A_GUI_Info<G, D>
{
    public D Data { get; set; }
}

It's not overly nice, but it does tie the two derived types to each other.

You would defined them like this:

public class HUDInfoData : A_Info_Data<HUDInfoData, HUDInfo>
{
}

public class HUDInfo : A_GUI_Info<HUDInfoData, HUDInfo>
{
}

Have you tried:

abstract class A_Info_Data { ... }
abstract class A_GUI_Info<T> where T: A_Info_Data { ... }

And now:

class CriticalData: A_Info_Data { ... }
class CriticalGui: A_GUI_Info<CriticalData> { ... }

The type parameter on the base class only exists on the base class. The more derived class has to define a new type parameter and pipe through the type to the base class's type parameter. This gives you a place to pose more generic constraints.

For example:

class HUDInfo<THudInfoData> : A_GUI_Info<THudInfoData> where THudInfoData : A_Info_Data

Now, HUDInfo<> can take any HudInfoData as long as it derives from A_Info_Data (or if it is A_Info_Data ). If you wanted to have HUDExtremelySpecificInfo which could only take HUDExtremelySpecificInfoData , that would look like:

class HUDExtremelySpecificInfo<THudInfoData> : A_GUI_Info<THudInfoData>
    where THudInfoData : HUDExtremelySpecificInfoData

If you never want to specify the type because you know that it will always be HUDExtremelySpecificInfoData , you can also declare either both:

class HUDExtremelySpecificInfo<THudInfoData> : A_GUI_Info<THudInfoData>
    where THudInfoData : HUDExtremelySpecificInfoData { .. }

class HUDExtremelySpecificInfo : HUDExtremelySpecificInfo<HUDExtremelySpecificInfoData> { .. }

(where you implement the non-generic HUDExtremelySpecificInfo in terms of the generic HUDExtremelySpecificInfo<> , and can use the generic one if there's a specific even more extremely specific info data subclass that you want to specify)

or just one:

class HUDExtremelySpecificInfo : A_GUI_Info<HUDExtremelySpecificInfoData> { .. }

Thank you all for giving constructive answers. What I try here is not working like preferred (pbbly not possible at all). This is what I came up with:

// abstract definitions
public abstract class AInfo
{
    public abstract void SetData(AInfoData data);
}
public abstract class AInfoData

// explicit definitions
public class WristInfo : AInfo
{
    public override void SetData(AInfoData data)
    {
        Data_Info_Wrist d = (Data_Info_Wrist)data; // cast to use
    }
}
public class Data_Info_Wrist : AInfoData

// runtime usage
public AInfo instance; (WristInfo)

public void Setup(AInfo info) { }

For Unity workflow I require the explicit class to be non-generic. So this workaround is possibly the best solution. The drawback: The desired type-safety is not given here.

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