C# 在泛型类C中继承#

C# 在泛型类C中继承#,c#,generics,inheritance,C#,Generics,Inheritance,我的大脑要爆炸了所以我想得到你的帮助。 请把我的问题想成程序员的难题。(事实上,这个问题对你们来说可能很简单,但对我来说不是。) 需要创建对象数组。例如,列出T是类的位置。(我将在下面描述T类)。此外,还需要创建包含此数组的“容器”以及使用此数组的一些方法。例如Add()、Remove(int IndexToRemove)。 类T必须有字段“Container”,这样,数组中的每个元素都可以知道它包含在哪里,并且可以访问它的容器的字段和方法。注意,在这种情况下,类T应该具有类型参数。事实上,事先

我的大脑要爆炸了所以我想得到你的帮助。 请把我的问题想成程序员的难题。(事实上,这个问题对你们来说可能很简单,但对我来说不是。)

需要创建对象数组。例如,列出T是类的位置。(我将在下面描述T类)。此外,还需要创建包含此数组的“容器”以及使用此数组的一些方法。例如Add()、Remove(int IndexToRemove)。 类T必须有字段“Container”,这样,数组中的每个元素都可以知道它包含在哪里,并且可以访问它的容器的字段和方法。注意,在这种情况下,类T应该具有类型参数。事实上,事先不知道使用哪种容器类型。 让我们将这个类容器表示为A,将类元素(类T)表示为AUnit

代码:

嗯。如果你还在读,让我们继续。现在我们需要创建类B和类BUnit,它们与类A和类Aunit非常相似。最后,这个谜题的主要问题是我们如何做到这一点?当然,我可以复制粘贴和位修改A和A,并创建此代码

class B
{
    public List<BUnit> Units; //Only Type Changing

    public B()//ctor Name changing...
    {
        Units = new List<BUnit>();//Only Type Changing
    }
    public void Add()
    {
        this.Units.Add(new BUnit(this));//Only Type Changing
    }
}
class BUnit
{
    public int SomeField;
    public B Container;//Only Type Changing
    public string Name { get; private set; }
    public A a; //NEW FIELD IS ADDED (just one)

    public BUnit(B container) //Ctor Name and arguments type changing 
    {
        this.SomeField = 43;
        this.Container = container;
        this.Name = "Default";

        this.a=new A(); //New ROW (just one)
    }
    public bool Rename(String newName)
    {
        Boolean res = true;
        foreach (BUnit unt in this.Container.Units) //Only Type Changing
        {
            if (unt.Name == newName)
            {
                res = false;
                break;
            }
        }
        if (res) this.Name = String.Copy(newName);
        return res;
    }
}
此构造可用于创建“非齐次树”

救命,我需要有人帮忙,只是没有人…。[披头士乐队]

我用CopyPaste创建了B和BUnit。 但如何使用“宏定义”或“泛型”、继承或其他优雅风格的东西来实现呢?(C#语言) 我认为没有理由描述我所有失败的尝试和子问题。主题已太长。:)


如果您仍然阅读并理解我想问的问题,非常感谢。

您需要实现一个基本类型,让我们称之为
UnitBase
,具有所有常见功能。我将按以下方式构造代码:

  • 为您的容器创建一个接口,这样您就可以将实现更改为更高性能的解决方案,而无需修改要添加到容器中的元素

    public interface IContainer
    {
        Q Add<Q>() where Q : UnitBase, new();
        IEnumerable<UnitBase> Units { get; }
    }
    
  • 为聚合所有常用功能的
    AUnit
    BUnit
    类型创建基类:

    public abstract class UnitBase
    {
        protected UnitBase()
        {
        }
    
        public IContainer Container { get; private set; }
        public int SomeField;
        public string Name { get; private set; }
        public void SetContainer(IContainer container)
        {
            Container = container;
        }
    
        public bool Rename(String newName)
        {
             if (Container.Contains(newName))
                 return false;
    
            this.Name = newName; //No need to use String.Copy
            return true;
        }
    }
    
  • 实现您的具体类型:

    public class BUnit : UnitBase
    {
        public int SpecificBProperty { get; private set; }
        public BUnit()
        {
        }
    }
    
  • 这种方法的缺点是什么?好的,容器必须是
    类型,我已经删除了泛型类型,因为它在这个特殊情况下没有做太多工作,因为它在泛型类型中是不变的

    此外,请记住,类型系统中的任何内容都无法避免以下情况:

    public class Container : IContainer
    {
        public Container()
        {
            list = new List<UnitBase>();
        }
    
        private List<UnitBase> list;
    
        public Q Add<Q>() where Q: UnitBase, new()
        {
            var newItem = Activator.CreateInstance<Q>();
            newItem.SetContainer(this);
            list.Add(newItem);
            return newItem;
        }
    
        public IEnumerable<UnitBase> Units => list.Select(i => i);
        public bool Contains(string name) =>
            Units.Any(unit => unit.Name == name);
    }
    
    myContainer.Add<BUnit>();
    myContainer.Add<AUnit>();
    
    myContainer.Add();
    myContainer.Add();
    
    如果在同一个容器中有两种不同的类型不是一种选择,那么整个设置就会崩溃。这个问题也出现在以前的解决方案中,因此它不是什么新问题,我只是忘了指出它。

    ,非常感谢您的建议。事实上,我不能说我完全理解你的答案,但利用你的想法,我已经做了我想做的

    看起来我的变种很好用。然而,我想听听你们(和每个人)对下面描述的代码的看法。此结构的主要目标是创建非齐次树。那么你能从这方面估计一下吗

    首先。我们需要为这两个类创建接口。我们在这里描述了所有“交叉使用”的函数

    public interface IUnit<T>
    {
        string Name { get;}
        void SetContainer(T t);
        bool Rename(String newName);   
    }
    public interface IContainer
    {
       bool IsNameBusy(String newName);
       int Count { get; }
    }
    
    代码:UnitBase

    class UnitBase<T> : IUnit<T> where T : IContainer
    {
        protected T Container;
        public string Name { get; private set; }
        public UnitBase()
        {
            this.Name = "Default";
        }
        public void SetContainer(T container)
        {
            this.Container = container;
        }
        public bool Rename(String newName)
        {
            bool res = Container.IsNameBusy(newName);
            if (!res) this.Name = String.Copy(newName);
            return !res;
        }
    }
    
    class UnitBase:IUnit其中T:IContainer
    {
    受保护的T形容器;
    公共字符串名称{get;private set;}
    公共单位库()
    {
    this.Name=“Default”;
    }
    公共容器(T容器)
    {
    this.Container=Container;
    }
    公共bool重命名(字符串newName)
    {
    bool res=Container.IsNameBusy(newName);
    如果(!res)this.Name=String.Copy(newName);
    返回!res;
    }
    }
    
    下一个。创建容器基

    集装箱基础应:

    1) 具有IContainer接口

    2) 包含有关其将包含的内容的信息:

     ... where U : IUnit<C>, new() 
    
    。。。其中U:IUnit,new()
    
    3) 还有。。。。有关于它本身的信息。我们需要将此信息作为参数传递给SetContainer()方法

    代码容器库:

    class ContainerBase<U, C> : IContainer //U - Unit Class.  C-Container Class
        where U : IUnit<C>, new()
        where C : ContainerBase<U, C>
    {
        protected List<U> Units;
        public U this[int index] { get { return Units[index]; } }
        public ContainerBase()//ctor
        {
            this.Units = new List<U>();
        }
        public void Add()
        {
            this.Units.Add(new U());
            this.Units.Last().SetContainer(((C)this));//may be a bit strange but actualy this will have the same type as <C>
        }
        public bool IsNameBusy(String newName)
        {
            bool res = false;
            foreach (var unt in this.Units)
            {
                if (unt.Name == newName)
                {
                    res = true;
                    break;
                }
            }
            return res;
        }
        public int Count { get { return this.Units.Count; } }
    }
    
    类容器基:IContainer//U-单元类。集装箱类
    其中U:IUnit,new()
    其中C:ContainerBase
    {
    受保护名单单位;
    公共U这个[int索引]{get{返回单位[index];}
    公共容器基()//
    {
    this.Units=新列表();
    }
    公共无效添加()
    {
    这个.Units.Add(新的U());
    this.Units.Last().SetContainer(((C)this));//可能有点奇怪,但实际上它的类型与
    }
    public bool IsNameBusy(字符串newName)
    {
    bool res=假;
    foreach(此.Units中的变量unt)
    {
    如果(unt.Name==newName)
    {
    res=真;
    打破
    }
    }
    返回res;
    }
    公共整数计数{get{返回this.Units.Count;}}
    }
    
    演员((TContainer)(this))可能有点奇怪。但是使用ContainerBase时,我们应该始终使用NewInheritorContainer。所以这个演员是什么都不做…看起来像

    最后。这些类可以像本例中那样使用

    class SheetContainer : ContainerBase<SheetUnit,SheetContainer> {public SheetContainer(){}}
    
    class SheetUnit : UnitBase<SheetContainer>
    {
        public CellContainer Cells;
        public PictureContainer Pictures;
        public SheetUnit()
        {
            this.Cells = new CellContainer();
            this.Pictures = new PictureContainer();
        }
    }
    
    class CellContainer : ContainerBase<CellUnit, CellContainer> { public CellContainer() { } }
    
    class CellUnit : UnitBase<CellContainer>
    {
        public string ValuePr;//Private Field
        private const string ValuePrDefault = "Default";  
        public string Value//Property for Value
        {
            //All below are Just For Example.
            get
            {
                return this.ValuePr;
            }
            set
            {
                if (String.IsNullOrEmpty(value))
                {
                    this.ValuePr = ValuePrDefault;
                }
                else
                {
                    this.ValuePr = String.Copy(value);
                }
            }
        }
        public CellUnit()
        {
            this.ValuePr = ValuePrDefault;
        }
    }
    
    class PictureContainer : ContainerBase<PictureUnit, PictureContainer> { public PictureContainer() { } }
    
    class PictureUnit : UnitBase<PictureContainer>
    {
        public int[,] Pixels{get;private set;}
        public PictureUnit()
        {
            this.Pixels=new int[,]{{10,20,30},{11,12,13}};
        }
        public int GetSizeX()
        {
            return this.Pixels.GetLength(1);
        }
        public int GetSizeY()
        {
            return this.Pixels.GetLength(0);
        }
        public bool LoadFromFile(string path)
        {
            return false;
        }
    }
    static void Main(string[] args)
        {
            SheetContainer Sheets = new SheetContainer();
            Sheets.Add();
            Sheets.Add();
            Sheets.Add();
            Sheets[0].Pictures.Add();
            Sheets[1].Cells.Add();
            Sheets[2].Pictures.Add();
            Sheets[2].Cells.Add();
    
    
            Sheets[2].Cells[0].Value = "FirstTest";
            bool res= Sheets[0].Rename("First");//res=true
            res=Sheets[2].Rename("First");//res =false
    
            int res2 = Sheets.Count;
            res2 = Sheets[2].Pictures[0].Pixels[1, 2];//13
            res2 = Sheets[2].Pictures.Count;//1
            res2 = Sheets[1].Pictures.Count;//0
            res2 = Sheets[0].Pictures[0].GetSizeX();//3
            Console.ReadKey();
        }
    
    class SheetContainer:ContainerBase{public SheetContainer(){}
    类别单位:UnitBase
    {
    公共细胞和容器细胞;
    公共图片容器图片;
    公共小型张组()
    {
    this.Cells=新的CellContainer();
    this.Pictures=新的PictureContainer();
    }
    }
    类CellContainer:ContainerBase{public CellContainer(){}
    类别单元:UnitBase
    {
    公共字符串ValuePr;//私有字段
    private const string ValuePrDefault=“Default”;
    公共字符串值//值的属性
    {
    //以下所有内容仅为示例。
    得到
    {
    返回此.ValuePr;
    }
    设置
    {
    if(String.IsNullOrEmpty(value))
    {
    
     class UnitBase<T> : IUnit<T> where T : IContainer
    
     SetContainer(T container).
    
    class UnitBase<T> : IUnit<T> where T : IContainer
    {
        protected T Container;
        public string Name { get; private set; }
        public UnitBase()
        {
            this.Name = "Default";
        }
        public void SetContainer(T container)
        {
            this.Container = container;
        }
        public bool Rename(String newName)
        {
            bool res = Container.IsNameBusy(newName);
            if (!res) this.Name = String.Copy(newName);
            return !res;
        }
    }
    
     ... where U : IUnit<C>, new() 
    
    class ContainerBase<U, C> : IContainer //U - Unit Class.  C-Container Class
        where U : IUnit<C>, new()
        where C : ContainerBase<U, C>
    {
        protected List<U> Units;
        public U this[int index] { get { return Units[index]; } }
        public ContainerBase()//ctor
        {
            this.Units = new List<U>();
        }
        public void Add()
        {
            this.Units.Add(new U());
            this.Units.Last().SetContainer(((C)this));//may be a bit strange but actualy this will have the same type as <C>
        }
        public bool IsNameBusy(String newName)
        {
            bool res = false;
            foreach (var unt in this.Units)
            {
                if (unt.Name == newName)
                {
                    res = true;
                    break;
                }
            }
            return res;
        }
        public int Count { get { return this.Units.Count; } }
    }
    
    class SheetContainer : ContainerBase<SheetUnit,SheetContainer> {public SheetContainer(){}}
    
    class SheetUnit : UnitBase<SheetContainer>
    {
        public CellContainer Cells;
        public PictureContainer Pictures;
        public SheetUnit()
        {
            this.Cells = new CellContainer();
            this.Pictures = new PictureContainer();
        }
    }
    
    class CellContainer : ContainerBase<CellUnit, CellContainer> { public CellContainer() { } }
    
    class CellUnit : UnitBase<CellContainer>
    {
        public string ValuePr;//Private Field
        private const string ValuePrDefault = "Default";  
        public string Value//Property for Value
        {
            //All below are Just For Example.
            get
            {
                return this.ValuePr;
            }
            set
            {
                if (String.IsNullOrEmpty(value))
                {
                    this.ValuePr = ValuePrDefault;
                }
                else
                {
                    this.ValuePr = String.Copy(value);
                }
            }
        }
        public CellUnit()
        {
            this.ValuePr = ValuePrDefault;
        }
    }
    
    class PictureContainer : ContainerBase<PictureUnit, PictureContainer> { public PictureContainer() { } }
    
    class PictureUnit : UnitBase<PictureContainer>
    {
        public int[,] Pixels{get;private set;}
        public PictureUnit()
        {
            this.Pixels=new int[,]{{10,20,30},{11,12,13}};
        }
        public int GetSizeX()
        {
            return this.Pixels.GetLength(1);
        }
        public int GetSizeY()
        {
            return this.Pixels.GetLength(0);
        }
        public bool LoadFromFile(string path)
        {
            return false;
        }
    }
    static void Main(string[] args)
        {
            SheetContainer Sheets = new SheetContainer();
            Sheets.Add();
            Sheets.Add();
            Sheets.Add();
            Sheets[0].Pictures.Add();
            Sheets[1].Cells.Add();
            Sheets[2].Pictures.Add();
            Sheets[2].Cells.Add();
    
    
            Sheets[2].Cells[0].Value = "FirstTest";
            bool res= Sheets[0].Rename("First");//res=true
            res=Sheets[2].Rename("First");//res =false
    
            int res2 = Sheets.Count;
            res2 = Sheets[2].Pictures[0].Pixels[1, 2];//13
            res2 = Sheets[2].Pictures.Count;//1
            res2 = Sheets[1].Pictures.Count;//0
            res2 = Sheets[0].Pictures[0].GetSizeX();//3
            Console.ReadKey();
        }