Curiously Recurring Template Pattern and generics constraints (C#)

后端 未结 2 889
萌比男神i
萌比男神i 2020-11-28 13:20

I would like to create a method in a base generic class to return a specialized collection of derived objects and perform some operations on them, like in the following exam

相关标签:
2条回答
  • 2020-11-28 13:34

    This might work for you:

    class Base<T> where T : Base<T>
    

    You can't constrain T to an open generic type. If you need to constrain T to Base<whatever>, you'll need to construct something like:

    abstract class Base { }
    
    class Base<T> : Base where T : Base { ... }
    
    0 讨论(0)
  • 2020-11-28 13:38

    I have used the following to create not a linked list, but a generecic linked tree. It works wonderfully nicely.

    public class Tree<T> where T : Tree<T>
    {
        T parent;
        List<T> children;
    
        public Tree(T parent)
        {
            this.parent = parent;
            this.children = new List<T>();
            if( parent!=null ) { parent.children.Add(this as T); }
        }
        public bool IsRoot { get { return parent == null; } }
        public bool IsLeaf { get { return children.Count == 0; } }
    }
    

    Example usage from Mechanics (Coordinate System Hierarchy)

    class Coord3 : Tree<Coord3>
    {
        Vector3 position;
        Matrix3 rotation;
        private Coord3() : this(Vector3.Zero, Matrix3.Identity) { }
        private Coord3(Vector3 position, Matrix3 rotation) : base(null) 
        {  
           this.position = position;
           this.rotation = rotation;
        }
        public Coord3(Coord3 parent, Vector3 position, Matrix3 rotation) 
           : base(parent)
        {
           this.position = position;
           this.rotation = rotation;
        }
        public static readonly Coord3 World = new Coord3();
    
        public Coord3 ToGlobalCoordinate()
        {
           if( IsRoot )
           { 
                return this;
           } else {
                Coord3 base_cs = parent.ToGlobalCoordinate();
                Vector3 global_pos = 
                          base_cs.position + base_cs.rotation * this.position;
                Matrix3 global_rot = base_cs.rotation * this.rotation;
                return new Coord3(global_pos, global_ori );
           }
        }
    }
    

    The trick is to initialize the root object with null parent. Remember you cannot do Coord3() : base(this) { }.

    0 讨论(0)
提交回复
热议问题