2009-08-25 2 views
10

나는 다음 예에서와 같이 파생 개체의 전문 수집을 반환하고 일부 작업을 수행 할 기본 제네릭 클래스의 메소드를 만들 싶습니다호기심 반복 템플릿 패턴 및 제네릭 제약 조건 (C#을)

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

는 어떻게 든 같은 제약 조건을 지정할 수를 지정할 필요가 그런 일을 할 것입니다?

+0

이와 같은 코드에 대해 더 나은 언어 지원을 추가하기 위해이 사용자 제안 사항을 작성했습니다. 투표 해주십시오. https://visualstudio.uservoice.com/forums/121579-visual-studio-ide/suggestions/32188474-support-this-as-a-return-type-to-make-building-f –

답변

22

이 당신을 위해 작동 할 수 있습니다 : 당신은 개방형 제네릭 형식에 T을 제한 할 수

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

. 당신이 Base<whatever>T을 제한해야하는 경우, 당신은 같은 것을 구성해야합니다 :

abstract class Base { } 

class Base<T> : Base where T : Base { ... } 
+0

정확히 내가 원했던 것 , 고마워요 :) –

+2

와우, 이건 합법적 인가요? – Qwertie

+1

Qwertie : 그래, 왜 안되니? –

8

내가 아닌 링크 된 목록을 생성하려면 다음을 사용하고 있지만, 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) { }.