代码之家  ›  专栏  ›  技术社区  ›  Paul Alexander

用于流利课堂的通用“T”

  •  13
  • Paul Alexander  · 技术社区  · 16 年前

    public class Field<T>
    {
        public Field<T> Name( string name )
        {
            _name = name;
            return this;
        }
    }
    
    public SpecialField<T> : Field<T>
    {
        public SpecialField<T> Special(){ return this; }
    }
    
    
    // !!! Arrgh. Special is not a member of the Field<T> class.
    var specialField = new SpecialField()
        .Name( "bing" )
        .Special();
    

    我尝试通过执行以下操作来解决这个问题,但它不是有效的C#:(但至少表达了我想如何编写接口代码。

    public class Field<T,TThis> : TThis
        where TThis : Field<T,TThis>
    {
        public TThis Name( string name ){...}
    }
    
    public SpecialField<T> : Field<T,SpecialField<T>>
    {
        public TThis Special(){ return this; }
    }
    
    1 回复  |  直到 6 年前
        1
  •  12
  •   Ryan    8 年前

    在浏览了其他一些流畅的API后,我找到了如何做到这一点。它不太干净,但工作得很好。基本上,您为要使用的每个派生类型引入一个中间基类,并将“TThis”类型传递给实际实现。

    public class FieldBase<T,TThis> 
        where TThis : FieldBase<T,TThis>
    {
        private string _name;
        public TThis Name( string name ) 
        {
            _name = name;
            return (TThis)this;
        }
    }
    
    public class Field<T> : FieldBase<T,Field<T>>{}
    
    public class SpecialFieldBase<T,TThis> : FieldBase<T,TThis>
        where TThis : SpecialFieldBase<T,TThis>
    {
        public TThis Special(){ return (TThis)this; }
    }
    
    public class SpecialField<T> : SpecialFieldBase<T,SpecialField<T>>{}
    
    
    // Yeah it works!
    var specialField = new SpecialField<string>()
        .Name( "bing" )
        .Special();