C# 继承的类引用基类';价值观 公共类父类 { 公共int-myId; 公共字符串commonField1; 公共字符串commonField2; 公共字符串commonField3; 公共字符串可变; 公开儿童名单; 公共父类(int-id) { myId=myId; } 公共儿童() { 对于(int i=0;i

C# 继承的类引用基类';价值观 公共类父类 { 公共int-myId; 公共字符串commonField1; 公共字符串commonField2; 公共字符串commonField3; 公共字符串可变; 公开儿童名单; 公共父类(int-id) { myId=myId; } 公共儿童() { 对于(int i=0;i,c#,class,inheritance,C#,Class,Inheritance,因为ChildClass仅存在于其父类的上下文中,并且将有9999999个子类。这就是创建所有commonField的999999副本,而实际上它只需要对其父项的引用。除了引用之外,ChildClass还需要存储的唯一真正的东西是change 如何做到这一点 当我需要孩子的时候,我几乎在想一个更好的方法就是只制作父类的9999999浅拷贝,然后只更改9999999可变字段。浅拷贝会引用commonField1还是会引用深拷贝值?有一点是正确的,那就是如果commonFieldX确实不变,那么会有

因为
ChildClass
仅存在于其父类的上下文中,并且将有9999999个子类。这就是创建所有
commonField
999999
副本,而实际上它只需要对其父项的引用。除了引用之外,
ChildClass
还需要存储的唯一真正的东西是
change

如何做到这一点


当我需要孩子的时候,我几乎在想一个更好的方法就是只制作父类的9999999浅拷贝,然后只更改9999999可变字段。浅拷贝会引用
commonField1
还是会引用深拷贝值?

有一点是正确的,那就是如果
commonFieldX
确实不变,那么会有大量重复数据

我看到了几种解决方案:

  • 偏好组合而非继承

    你为什么要继承遗产?如果没有多态行为,那么只需将基类实例传递给10000个子类并称之为good:

    public class ParentClass
    {
        public int myId;
        public string commonField1;
        public string commonField2;
        public string commonField3;
        public string changeable;
        public List<ChildClass> children;
    
        public ParentClass(int id)
        {
            myId = myId;
        }
    
        public createChildren()
        {
            for(int i = 0; i < 999999; i++) 
            {
                children.Add(new ChildClass(id));
            }
        }
    }
    
    public class ChildClass : ParentClass
    {
        public ChildClass(int id) : base (id) 
        {
            myId = myId;
            changeable = "new";
        }
    }
    
    请注意,其中一些字段可能受
    保护
    而不是
    公共
    ,并且您应该始终通过属性而不是直接公开公共字段。当然,如果有多个
    ParentClass
    实例的这些字段的值不同,这是不可能的


  • 如果子级和父级应该有某种关系(即共享方法/属性的公共父级类),但子级需要与父级共享属性,则可以将属性请求重定向到父级(注意,获取深度嵌套子级的属性非常慢):

    公共类节点
    {
    公共虚拟字符串字段{get{return parent!=null?parent.Field:Field;}
    公共节点父节点;
    公开儿童名单;
    公共节点()
    {
    children=新列表();
    }
    公共儿童()
    {
    对于(int i=0;i<999999;i++)
    {
    添加(新的ChildNode(i,this));
    }
    }
    }
    公共类ChildNode:节点
    {
    公共重写字符串字段{get{return parent.Field;}}
    公共子节点(节点父节点)
    {
    this.parent=parent;
    }
    }
    公共类RootNode:Node
    {
    公共重写字符串字段{get{返回“Root”;}
    公共根节点()
    {
    this.parent=null;
    }
    }
    
    听起来你根本不应该使用继承。听起来孩子并不是真正的父母——它只是需要一个对父母的引用。首先,为什么要让孩子扩展父母?
    可更改的
    是否需要位于父级中?我们目前确实没有足够的上下文来建议其他代码……是的,
    changable
    需要在
    Parent
    中,不清楚您试图实现什么。如果只使用两个公共字段,为什么
    ChildClass
    派生自
    ParentClass
    。您不应该从只包含公共字段的公共接口或基类派生吗?我认为你混淆了包装和继承。我学到的是基类/派生类,而不是接口。谷歌会界面,看看这是否更好如果
    ChildClass
    真的是一个“
    ParentClass
    ,那么它也会有一个子类列表,每个子类都会有一个子类列表,等等。我同意继承似乎不是正确的解决方案。1)我该怎么做ChildClass.commonField1?2.)ParentClass确实有不同的值。@LearningJrDev 1)要么将父实例作为属性公开(例如
    c.parent.CommonField1
    ),要么创建传递属性。请注意,通过特性通常是一种设计气味。
    public createChildren()
    {
        for(int i = 0; i < 999999; i++) {
             children.Add(new ChildClass(id, this));
        }
    }
    
    public class ChildClass
    {
         public ChildClass(int id, ParentClass parent) : base (id) 
         {
               myId = myId; //This shouldn't be part of the base class?
               changeable = "new"; //Same here
               myParent = parent;
         }
    }
    
    public class ParentClass
    {
        public int MyId {get; set;}
        public static string CommonField1 {get; set;}
        public static string CommonField2 {get; set;}
        public static string CommonField3 {get; set;}
        public string Changeable {get; set;}
    
    public class Node
    {
        public virtual string Field {get {return parent != null ? parent.Field : field;}}
    
        public Node parent;
        public List<Node> children;
    
        public Node()
        {
            children = new List<Node>();
        }
    
        public createChildren()
        {
            for(int i = 0; i < 999999; i++) 
            {
                children.Add(new ChildNode(i, this));
            }
        }
    }
    
    public class ChildNode : Node
    {
        public override string Field {get {return parent.Field;}}
        public ChildNode(Node parent)
        {
            this.parent = parent;
        }
    }
    
    public class RootNode : Node
    {
        public override string Field {get {return "Root";}}
        public RootNode()
        {
            this.parent = null;
        }
    }