C# 通用';t这';对于流利的课程
我正在构建一个fluent接口,其中有一个基类,包含fluent逻辑的大部分,还有一个派生类,添加了一些专门的行为。我面临的问题是从派生类型的实例调用时基类中fluent方法的返回类型。在调用基类的方法之后,只有基类的方法可用于进一步的流畅调用 改变调用方法的顺序将有助于编译,但会降低可读性,这在某种程度上是fluent接口的要点。是否有一种方法可以为基类定义某种类型的“This”类型,以便所有方法都返回相同的类型 例子C# 通用';t这';对于流利的课程,c#,generics,fluent,fluent-interface,C#,Generics,Fluent,Fluent Interface,我正在构建一个fluent接口,其中有一个基类,包含fluent逻辑的大部分,还有一个派生类,添加了一些专门的行为。我面临的问题是从派生类型的实例调用时基类中fluent方法的返回类型。在调用基类的方法之后,只有基类的方法可用于进一步的流畅调用 改变调用方法的顺序将有助于编译,但会降低可读性,这在某种程度上是fluent接口的要点。是否有一种方法可以为基类定义某种类型的“This”类型,以便所有方法都返回相同的类型 例子 公共类字段 { 公共字段名(字符串名) { _名称=名称; 归还这个; }
公共类字段
{
公共字段名(字符串名)
{
_名称=名称;
归还这个;
}
}
公共专用字段:字段
{
public SpecialField Special(){返回此;}
}
// !!! 啊。Special不是Field类的成员。
var specialField=new specialField()
.姓名(“必应”)
.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; }
}
公共类字段:t此
这是什么地方
{
public t此名称(字符串名称){…}
}
公共专用字段:字段
{
public t此特殊(){返回此;}
}
在浏览了其他一些fluent API之后,我找到了如何实现它的方法。虽然没有那么干净,但效果很好。基本上,为要使用的每个派生类型引入一个中间基类,并将“ttthis”类型传递给实际实现
样品
公共类现场数据库
这是什么地方:野战基地
{
私有字符串\u名称;
公共t此名称(字符串名称)
{
_名称=名称;
把这个退回来;
}
}
公共类字段:FieldBase{}
公共类特殊字段数据库:FieldBase
此处:特殊字段数据库
{
public ttthis Special(){return(ttthis)this;}
}
公共类SpecialField:SpecialFieldBase{}
//是的,很管用!
var specialField=new specialField()
.姓名(“必应”)
.Special();
这看起来与协变和反变有关。在《物体理论》一书中,他们花了一两节的时间讨论了“自我”在打字中所代表的困难,这就是为什么要找出“自我”或“这”的类型是有关协变和反变问题的主要动机。
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; }
}
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();