C# 将泛型的实例作为参数发送

C# 将泛型的实例作为参数发送,c#,generics,cross-reference,C#,Generics,Cross Reference,我有一个抽象组类和一个抽象成员类。Group类有一个名为Member的成员类字段(属性),Member有一个名为Group的Group类字段 它们都必须以这种方式继承,因此我们有DerGroup和DerMember,DerGroup的成员字段为DerMember,DerMember的组字段为group类 我正试图用泛型来解决这个问题 abstract class Member { public Group<Member> group; public void Init

我有一个抽象组类和一个抽象成员类。Group类有一个名为Member的成员类字段(属性),Member有一个名为Group的Group类字段

它们都必须以这种方式继承,因此我们有DerGroup和DerMember,DerGroup的成员字段为DerMember,DerMember的组字段为group

我正试图用泛型来解决这个问题

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);
    }
}
抽象类成员
{
公共团体;
公共void Init(组grp)
{
组=玻璃钢;
}
}
抽象类组,其中T:Member
{
公共事务委员会成员;
公共成员()
{
//这里有一个错误:无法将组转换为组
成员:Init(本);
}
}
如果组是泛型的,如何将该组实例发送到其成员实例?我使用泛型来继承组和成员类并保存它们的关系。就像这样:

class Student : Member {}
class ClassRoom<T> : Group<Member> where T : Student {}
班级学生:成员{}
班级教室:组,其中T:Student{}
所以我们可以有:typeof(class.member)=Student,而不是member


请告诉我如何正确声明
Member.Init()
函数或如何完成此操作。

我不太明白您试图用这些类构建什么(我的意思是,您的核心业务),但您可以引入一个接口:

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 { }
抽象类成员
{
公共i组;
公共void Init(IGroup grp)
{
组=玻璃钢;
}
}
接口I组,其中T:成员
{
T成员{get;set;}
}
抽象类组:IGroup
{
公共成员成员{get;set;}
公共成员()
{
成员:Init(本);
}
}
班级学生:成员{}
班级教室:组,其中T:Student{}

工作。

我担心你可能已经陷入了疯狂的兔子洞。如果你环顾四周,你会看到我的爪痕

这些类之间的关系很难理解,因为它表示一个组只能有一个成员,而一个成员只能属于一个组

看起来你要做的是循环的。您正在尝试确保组只有一种成员,并且成员只属于包含该组成员的组。。。等等

问题是,为什么需要对这两种方式进行约束?鉴于此:

class Group<T> : Group where T : Member
现在,组可以受成员类型的约束,但成员具有对非约束组集的引用


避免成员引用组可能更简单。如果您想知道成员所在的组,请查询这些组以查看哪些组包含给定的成员。

这是否简化了您所需的内容?没有要实现的抽象方法
member.Init((组)(对象)this)
很难看,但它确实有效。我实际上不需要它们抽象。这只是为了显示组和成员将被继承。是的,我正在考虑转换为请求的类型,但我认为有一种更好的方法可以做到。如果您将代码重写为更基于接口(可以使用协方差)的话,可能会有和/或省去不必要的泛型,更多地依赖继承。但是,如果我们认为您的代码是固定的,并且假设您使用泛型是必要的,那么我非常确定强制转换也是同样必要和不可避免的。请注意,转换是不安全的,如果您声明
class-school:Group-where T:Student
,转换将在运行时失败。这个声明是可能的,而且似乎是合理的,这一事实已经表明您的设计可能受到怀疑。您能演示如何测试此代码吗?这行得通吗:var cr=新教室()//cr.member.GetType()必须是学生。@user1537809当然,我刚刚添加了一个提琴。好的。。。但是,如果您在“var c=new教室(){member=new Student()?这正是我试图避免的。我想从组继承课堂,从成员继承学生,这样课堂的字段成员就变成了学生的类型。@user1537809使用接口与成员字段的显式赋值无关,即使不使用接口,也需要这样做。您需要使用类似于
new Student()
的内容初始化成员字段,否则
InitMember
方法将抛出一个exception,因为
member
将为null。另一方面,为了使教室的字段成员成为学生类型,没有必要将
new Student()
显式分配给
member
,如果您编写此代码,您将注意到
member
属于
Student
类型,而不管
member=new Student()
。看到您的爪形标记。。。谢谢你,我想我成功了!组继承组是神奇的。
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);
    }
}