Inheritance of nested generics / nested generics in abstract class C# - 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.

Related

How to declare a list so it contains a generic class no matter the generic type?

I am looking for a way to declare a List that can contain any generic class instances, no matter the generic type of these instances. Perhaps a way to declare the List without having to specify the generic type of the class ?
public class Character {}
public class Hero : Character {}
public class Creature : Character {}
public abstract class ActorController<T> where T : Character
{
protected T actor;
}
public class CharacterController : ActorController<Character> {}
public class HeroController : ActorController<Hero> {}
public class CreatureController : ActorController<Creature> {}
public class Zone
{
// If it is even possible, what should I put instead of the ???
// so the List understands that the generic type doesn't matter
// and that I want any type of ActorController in it ?
private List<ActorController<???>> actorControllers;
}
I specify that I am trying to avoid declaring a regular class or interface that would serve as a parent of ActorController, as I would loose the interest of having a dynamic Actor property by doing so.
Thank you by advance, and sorry if I am misusing the jargon.
You can make a covariant interface for it:
public interface IActorController<out T> where T : Character {
}
Then have ActorController<T> implement that interface:
public abstract class ActorController<T> : IActorController<T> where T : Character
{
protected T actor;
}
Then you can make your list be of type List<IActorController<Character>>, and you can add any type to it:
public class Zone
{
public List<IActorController<Character>> actorControllers;
}
/* ... */
var heroController = new HeroController();
var creatureController = new CreatureController();
myZone.actorControllers.Add(heroController);
myZone.actorControllers.Add(creatureController);
You just need to make sure anything you want to use on the list members is in the interface (or cast it)
Simple proof (based on your code, a bit modified to show some result): https://dotnetfiddle.net/KY2pMP (updated to also show correct Character inheritance)

How to add the same functionality to different base classes without duplicating code? [duplicate]

I am trying to find a way to derive a class from a generic base class. Say:
sealed public class Final : Base<Something>
{
}
public class Base<T> : T
where T : Anything // <-- Generics do not allow this
{
}
In C# this does not seem to be possible.
Is there any other solution to achieve something similar to this?
I found this StackOverflow question, but it doesn't seem to solve the issue, or at least I do not understand how it should.
EDIT:
The result I'd like to get is to be able to do something like that:
Anything[] anything;
//Assign some Instances to anything
foreach(Final final in anything){
//do something with final
}
The result I'd like to get is to be able to do something like that:
Anything[] anything;
//Assign some Instances to anything
foreach(Final final in anything){
//do something with final
}
Your foreach loop suggests this: class Anything : Final { … }.
This obviously turns around the inheritance hierarchy as you planned and named it. (You cannot have cycles in your inheritance relationships).
public class Base<T> : T where T : Anything { …
Let me elaborate on this part for a bit. I'll reduce your example even further to just class Base<T> : T.
This is not possible, for good reason. Imagine this:
class Base<T> : T
{
public override string Frobble()
{
Fiddle();
return "*" + base.Frobble() + "*";
}
}
class A
{
public sealed string Frobble() { … }
}
class B
{
}
class C
{
public virtual string Frobble() { … }
}
abstract class D
{
public abstract void Fiddle();
public virtual string Frobble() { … }
}
class E
{
public void Fiddle() { … }
public virtual string Frobble() { … }
}
You get all kinds of absurd situations if class Base<T> : T were allowed.
Base<A> would be absurd because Frobble cannot be overridden in a derived class.
Base<B> would be absurd because you cannot override a method that
doesn't exist in the base class.
Base<C> doesn't work because there is no Fiddle method to call.
Base<D> would not work because you cannot call an abstract method.
Only Base<E> would work.
How would the compiler ever know how to correctly compile Base<T> and analyse code that depends on it?
The point is that you cannot derive from a class that is not known at compile-time. T is a parameter, i.e. a variable, a placeholder. So class Base<T> : T is basically like saying, "Base<T> inherits from some (unknown) class". Class inheritance is a type relationship that requires both involved types to be known at compile-time. (Actually, that's not a super-precise statement because you can inherit from a generic type such as class SpecialList<T> : List<T>. But at the very least, the derived class has to know what members (methods, properties, etc.) are available in the base class.)
Is this what you want?
sealed public class Final : Base<int>{
}
public class Base<T> {
}
You could only do this if Final would be a generic class as well, like so:
public sealed class Final<T> : Base<T>
Then you can put a type restraint on T as either a class, to allow only reference types as T, or an instance of Base<T>, to allow only types that derive from Base<T>:
public class Base<T> where T : Base<T>
I don't know the context of this question, but I ran into same question with a project where I had to make it possible to extend the base class which is already derived by many others. Like:
abstract class Base {}
class FinalA : Base {}
class FinalB : Base {}
// Now create extended base class and expect final classes to be extended as well:
class BetterBase : Base {}
The solution was to create common ancestor and connect through properties:
abstract class Foundation {}
abstract class Base : Foundation
{
Foundation Final { get; }
}
class FinalA : Foundation {}
class FinalB : Foundation {}
class FinalC : Foundation
{
Foundation Base { get; }
}
// Here's the desired extension:
class BetterBase : Base {}
Now BetterBase has connection to final class and if needed, the final classes could have connection with (Better)Base also, as shown in FinalC class.

Generic inherited type restriction in C#

I have an inelegant solution for what I need, but am looking for an elegant solution to replace it.
The following code doesn't compile, but represents what I would like to do:
interface IWebService
{
}
abstract class BaseClient<T>
{
}
class SpecializedClient : BaseClient<IWebService>
{
}
class ClientHelper<T> where T : BaseClient<*>
{
}
Where the T in ClientHelper<T> is any class that extends BaseClient regardless of the templated type passed in.
The inelegant solution I found is:
class ClientHelper<T, U> where T : BaseClient<U> {}
The reason this becomes inelegant is my project ends up with a class similar to:
class MyClass<A, B, C, D, E, F, G> where A : MyBaseClass<B, C, D, E, F, G>
All the way down to the base class that takes a single type. Is this simply the cost of having a complex inheritance tree of generic classes or is there a simpler way to do this while retaining type restrictions on the templated types?
Your "inelegant" solution is the right one if the public interface of BaseClient exposes it's generic type parameter in any way.
So assuming BaseClient is not as you defined it:
abstract class BaseClient<T>
{
//Something about T here
}
Then T is part of the public interface contract of BaseClient, and therefore part of the public interface contract of ClientHelper (again, assuming that BaseClient<U> is exposed via the interface of ClientHelper).
On the other hand, let's assume it actually is as your example puts it:
abstract class BaseClient<T>
{
//Nothing about T here
}
In that case, you can do:
interface IBaseClient
{
//Nothing about T here
}
abstract class BaseClient<T> : IBaseClient
{
// Whatever you like here
}
and ClientHelper becomes:
class ClientHelper<T> where T : IBaseClient
{
}
One option seems to be:
interface IWebService
{
}
interface IClient<out T>
{
}
abstract class BaseClient<T> : IClient<T>
{
}
class SpecializedClient : BaseClient<IWebService>
{
}
class ClientHelper<T> where T : IClient<object>
{
}
However that will only work if you BaseClient only returns T and never accepts it.

Redefine method return type in derived class without generics

TL;DR:
Is there some way to add an abstract method to a base class that allows derived classes to override the method's return type, without the use of generics, and without the use of the new keyword?
I'm working on developing some custom templates for LLBLGen Pro. In the process, I refuse to change the default templates that LLBLGen Pro offers, so that my approach doesn't overwrite other peoples' files if they choose to implement my templates.
One task I've started working on (and made good headway toward) is developing a template that generates a DTO for each entity. Along those lines, one objective is to provide my entities with a ToDTO() method. In the interest of generic programming, I've decided to define this method within a common base class, and this is where my trouble starts.
Keep in mind that the purpose of defining the ToDTO() method in the base class is because I'm looking to create a generic repository (with a Fetch() method, for example) that I'd like to have work off the CommonEntityBase, as opposed to a specific entity.
LLBLGen defines its CommonEntityBase class like so:
public abstract partial class CommonEntityBase : EntityBase2 {
// LLBLGen-generated code
}
My original plan was to add my method to another partial class like so:
public abstract partial class CommonEntityBase {
public abstract CommonDTOBase ToDto();
}
I thought that the inherited classes would be able to define the return type in their methods as a type derived from the base class's return type, like so:
public partial class PersonEntity : CommonEntityBase {
public override PersonDTO ToDto(){ return new PersonDTO(); }
}
but I was wrong.
My second attempt was to define the class using generics, as such:
public abstract partial class CommonEntityBase<T> : CommonEntityBase
where T : CommonDTOBase {
public abstract T ToDto();
}
Simple enough. All I'd have to do is have my generated entity classes inherit from this new entity base. Just one caveat. As I don't want to overwrite LLBLGen's templates, it's back to partial classes.
LLBLGen's individual entities have this definition:
public partial class PersonEntity : CommonEntityBase {
// LLBLGen-generated code
}
And herein lies my problem. In order for my method to work, I would have to create my own partial class with this definition:
public partial class PersonEntity : CommonEntityBase<PersonDTO> {
public override PersonDTO ToDto(){ return new PersonDTO(); }
}
Of course, this isn't possible, because, as I now know,
All of the parts [of a partial class] that specify a base class must agree, but parts that omit a base class still inherit the base type.
The third thing I was going to attempt was simply overriding the base class's function definition with the new keyword:
public abstract partial class CommonEntityBase {
public virtual CommonDTOBase ToDto(){ return null; }
}
public partial class PersonEntity : CommonEntityBase {
public new PersonDTO ToDto(){ return new PersonDTO(); }
}
However, this defeats the purpose of my approach completely, as I want to be able to access PersonEntity's ToDTO() method when it's cast as a CommonEntityBase. With this approach, doing:
CommonEntityBase e = new PersonEntity();
var dto = e.ToDto();
would result in dto being null, which I don't want.
I've come across various links discussing my first approach, and why it won't work, and typically pointing to my generic approach as a solution in the general sense. However, in my situation, generics do not appear to work.
All this to ask whether or not what I'm trying to accomplish is possible.
Is there some way to add an abstract method to a base class that allows derived classes to override the method's return type, without the use of generics, and without the use of the new keyword?
Or perhaps I'm approaching this from the wrong angle, and there's some other technique that could solve my problems?
EDIT
Here's a use-case for what I'd like to accomplish with the entities, taking Porges's approach:
public class BaseRepository<D,E> where D : CommonDTOBase where E : CommonEntityBase,new
public D Get(Guid id){
var entity = new E();
entity.SetId(id);
// LLBLGen adapter method; populates the entity with results from the database
FetchEntity(entity);
// Fails, as entity.ToDto() returns CommonDTOBase, not derived type D
return entity.ToDto();
}
}
Instead of:
public abstract partial class CommonEntityBase {
public abstract CommonDTOBase ToDto();
}
public partial class PersonEntity : CommonEntityBase {
public override PersonDTO ToDto(){ return new PersonDTO(); }
}
Why are you not just returning a DTO like this:
public abstract partial class CommonEntityBase {
public abstract CommonDTOBase ToDto();
}
public partial class PersonEntity : CommonEntityBase {
// changed PersonDTO to CommonDTOBase
public override CommonDTOBase ToDto(){ return new PersonDTO(); }
}
I think that's more idiomatic for OO code. Is there a reason you need to know the exact type of the DTO?
I don't know LLBLGen, but I believe you could solve your problem this way, by introducing an interface to hold the type parameter:
public interface DTOProvider<T> where T : CommonDTOBase {
public T ToDTO();
}
And then for your entity classes, do this:
public partial class PersonEntity : CommonEntityBase, DTOProvider<PersonDTO> {
public PersonDTO ToDto() { return new PersonDTO(); }
}
Because partial classes can introduce different interfaces, this works. The only sadness is that a cast is required to get access to the method via the base type:
public void DoSomethingWithDTO<T>(CommonBaseEntity entity)
where T : CommonDTOBase {
T dto = ((DTOProvider<T>) entity).ToDTO();
...
}
Of course, you can call ToDTO directly without the cast when you have a reference of one of the entity derived types:
public void DoSomethingWithPersonDTO(PersonEntity entity)
{
PersonDTO dto = entity.ToDTO();
...
}
If you are using .NET Framework 4, you can use generic variance to make the DTOProvider interface easier to use from code that just cares about working with CommonDTOBase by declaring the DTO type covariant:
public interface DTOProvider<out T> where T : CommonDTOBase {
public T ToDTO();
}
(Notice the 'out'.) Then your DoSomethingWithDTO method doesn't need the type parameter:
public void DoSomethingWithDTO(CommonBaseEntity entity) {
CommonDTOBase dto = ((DTOProvider<CommonDTOBase>) entity).ToDTO();
...
}
It is tempting to try and declare : CommonBaseEntity, DTOProvider<T> on the CommonBaseEntity partial class. Unfortunately that doesn't work, because when the partial definitions are merged the type parameter is carried over and your CommonBaseEntity type ends up being a generic type, which it looks like is what got you into a bind in the first place.

How do I declare the constructor for a generic class with a non-generic base class with parameters

I have a base class which is non-generic with a derived generic class. The AbstractRepository and ILoggingManager are provided by the IoC framework.
Base Class
public abstract class EventHandlerBase
: AbstractDataProvider
, IEventHandler
{
public EventHandlerBase(
AbstractRepository data,
ILoggingManager loggingManager
)
: base(data, loggingManager)
{
}
}
Derived Class
public abstract class EventHandlerBase<TDetail>
: EventHandlerBase
where TDetail : Contracts.DeliveryItemEventDetail
{
}
I would like to declare a constructor in the derived class that will call the non-generic base class, but I do not know the syntax.
Should it not be more like:
public abstract class EventHandlerBase<TDetail> : EventHandlerBase
where TDetail : Contracts.DeliveryItemEventDetail
{
public EventHandlerBase(AbstractRepository data, ILoggingManager loggingManager)
: base(data, loggingManager)
{
// Initialize generic class
}
}
public class EventHandlerBase(AbstractRepository data,
ILoggingManager loggingManager)
: base(data, loggingManager)
{
// Whatever
}
should work fine. If it doesn't, could you show the problems you're getting?
EDIT: I think the whole base class thing may be clouding the issue here. When you declare a constructor in a generic type, you don't specify the type parameters. For example, List<T> would look something like:
public class List<T>
{
public List()
{
}
}
The idea is that within the class declaration, T is already known - you only specify type parameters when you want to add more of them, e.g. for a generic method like ConvertAll.

Categories