代码之家  ›  专栏  ›  技术社区  ›  Paolo Tedesco

奇怪的重复模板模式和泛型约束(c)

  •  10
  • Paolo Tedesco  · 技术社区  · 15 年前

    我希望在基泛型类中创建一个方法,以返回派生对象的专门集合,并对它们执行一些操作,如下面的示例中所示:

    using System;
    using System.Collections.Generic;
    
    namespace test {
    
        class Base<T> {
    
            public static List<T> DoSomething() {
                List<T> objects = new List<T>();
                // fill the list somehow...
                foreach (T t in objects) {
                    if (t.DoSomeTest()) { // error !!!
                        // ...
                    }
                }
                return objects;
            }
    
            public virtual bool DoSomeTest() {
                return true;
            }
    
        }
    
        class Derived : Base<Derived> {
            public override bool DoSomeTest() {
                // return a random bool value
                return (0 == new Random().Next() % 2);
            }
        }
    
        class Program {
            static void Main(string[] args) {
                List<Derived> list = Derived.DoSomething();
            }
        }
    }
    

    我的问题是要做这样的事情,我需要指定一个约束

    class Base<T> where T : Base {
    }
    

    是否可以以某种方式指定这样的约束?

    2 回复  |  直到 11 年前
        1
  •  22
  •   Mehrdad Afshari    15 年前

    这可能对您有用:

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

    你不能约束 T 到打开的泛型类型。如果你需要约束 T Base<whatever> ,您需要构造如下内容:

    abstract class Base { }
    
    class Base<T> : Base where T : Base { ... }
    
        2
  •  8
  •   luke    11 年前

    我使用下面的代码创建的不是一个链表,而是一个generecic链表树。它工作得非常好。

    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; } }
    }
    

    力学示例用法(坐标系层次)

    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 );
           }
        }
    }
    

    技巧是用初始化根对象 null 起源。记住你 不能 Coord3() : base(this) { } .