简体   繁体   中英

Send Instance of Generic as a parameter

I have an abstract Group class and an abstract Member class. Group class has a field (property) of Member class called member , and Member has a field of Group class called group .

They both must be inherited that way, so we have DerGroup and DerMember and DerGroup has the member field of DerMember and DerMember has the group field of Group class.

I am trying to use Generics for that.

abstract class Member
{
    public Group<Member> group;
    public void Init(Group<Member> grp)
    {
        group = grp;
    }
}

abstract class Group<T> where T : Member
{
    public T member;
    public void InitMember()
    {
        // Here I have an Error: Can't convert Group<T> to Group<Member>
        member.Init(this);
    }
}

How do I send this Group instance to its Member instance if Group is Generic? I am using Generics to be able to inherit Group and Member classes and save their relations. Like that:

class Student : Member {}
class ClassRoom<T> : Group<Member> where T : Student {}

So we can have this: typeof(ClassRoom.member) = Student , and not Member

Give me any help of how to properly declare Member.Init() function or get this done.

I am afraid you may have gone down the GRHOM - Generic Rabbit Hole of Madness. If you look around you'll see my claw marks.

The relationship between these classes is very difficult to follow because it indicates that a group can only have one member and a member can only belong to one group.

What it looks like you're trying to do is circular. You're trying to ensure that groups only have one sort of member, and members only belong to groups which contain members which are only members of that sort of group... etc.

The question is, why do you need to constrain this both ways? Given this:

class Group<T> : Group where T : Member

You've already ensured that a Group can only contain Member or a subclass of Member - whatever T is when you define your concrete class.

Why, then, does a Member need to also specify that it can only belong to groups which can only have it as a member? That constraint has already been accomplished.

Assuming that groups must contain references to members and members to groups, you could do this:

abstract class Member
{
    private List<Group> Groups { get; } = new List<Group>();

    internal void AddGroup(Group group)
    {
        Groups.Add(group);
    }
}

abstract class Group
{
    protected List<Member> Members { get; } = new List<Member>();
}

abstract class Group<TMember> :Group  where TMember : Member
{
    void AddMember(TMember member)
    {
        Members.Add(member);
        member.AddGroup(this);
    }
}

Now groups can be constrained by the type of members, but members has a reference to a non-constrained set of groups.

It might be simpler just to avoid having members reference groups. If you want to know which groups a member is in, query the groups to see which ones contain a given member.

I don't really understand what you're trying to build with these classes (I mean, your core business), but you could introduce an interface:

abstract class Member
{
    public IGroup<Member> group;
    public void Init(IGroup<Member> grp)
    {
        group = grp;
    }
}

interface IGroup<T> where T : Member
{
    T member { get; set; }
}

abstract class Group<T> : IGroup<Member>
{
    public Member member { get; set; }

    public void InitMember()
    {
        member.Init(this);
    }
}

class Student : Member { }

class ClassRoom<T> : Group<Student> where T : Student { }

Working fiddle 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