C#用链式方法表达循环嵌套

2019-12-30 12:31:30王振洲

结构更合理,逻辑更清晰,但是一堆lambda嵌套,太丑了,也不是我要的效果,我要的是类似这样的:

obj.Try("A").Try("B").Try("C").Try("D").Try2("A").Try2("B").Try2("C").Try2("D").Write();

四.继续向目标逼近。

由于要延迟,所以必须先把要被调用的方法的引用“告诉”上一级,当上一级执行for的时候,就能调用下一级的方法。于是我想到了一个“回调链”

所以,执行链式方法是在构造回调链,最后的方法再通过调用链头(Head)的某个方法启动真正要执行的整个逻辑。

延迟计算是从Linq借鉴和学习来的,构造Linq的过程并没有执行,等到了执行ToList, First等方法时才真正去执行。

我想构造回调链每一步都是一个固定的方法,这里随便起用了T这个极短名称,而每一步后期计算时要执行的方法可灵活指定。于是有了第3版:


static Seat data = new Seat(); //借用Seat保存数据
public Seat2(string name, Seat2 parent, Action<Seat2> method)
{
this.Name = name;
this.Parent = parent;
if (parent != null)
parent.Child = this;
this.Method = method;
}
public static void Run()
{
new Seat2("A", null, me => me.Try())
.T("B", me => me.Try())
.T("C", me => me.Try())
.T("D", me => me.Try())
.T("A", me => me.Try2())
.T("B", me => me.Try2())
.T("C", me => me.Try2())
.T("D", me => me.Try2())
.P().Start();
}
public Seat2 T(string name, Action<Seat2> method)
{
return new Seat2(name, this, method);
}
public void Try()
{
for (int i = 0; i < 4; i++)
{
if (data.IsSelected(0, i))
continue;
data.Selected(0, i, this.Name);
if (this.Child != null)
{
this.Child.Method(this.Child);
}
data.UnSelected(0, i);
}
}
public void Try2()
{
for (int i = 0; i < 5; i++)
{
if (i == 1)
continue;
if (data.IsSelected(1, i))
continue;
if (data.IsSelected(0, i, this.Name))
continue;
data.Selected(1, i, this.Name);
if (this.Child != null)
{
this.Child.Method(this.Child);
}
data.UnSelected(1, i);
}
} 

五.解耦

这种调用方式,是满意了。但是运算框架与具体的算法耦合在一起,如果能把运算框架提取出来,以后写具体的算法也方便许多。于是经过苦逼的提取,测试,踩坑,最终出现了第4版:


//运算框架
class ComputeLink<T> where T : ISeat
{
ComputeLink<T> Parent { get; set; } //父节点,即上一级节点
ComputeLink<T> Child { get; set; } //子节点,即下一级节点
T Obj { get; set; } //当前节点对应的算法对象,可以看作业务对象
public ComputeLink(T obj, ComputeLink<T> parent, Action<T> method)
{
if (obj == null)
throw new ArgumentNullException("obj");
this.Obj = obj;
this.Obj.Method = x => method((T)x);
if (parent != null)
{
this.Parent = parent;
parent.Child = this;
parent.Obj.Child = this.Obj;
}
}
public static ComputeLink<T> New(T obj, Action<T> method)
{
return new ComputeLink<T>(obj, null, method);
}
public ComputeLink<T> Do(T obj, Action<T> method)
{
return new ComputeLink<T>(obj, this, method);
}
public ComputeLink<T> Head //链表的头
{
get
{
if (null != this.Parent)
return this.Parent.Head;
return this;
}
}
public void Action() //启动(延迟的)整个计算
{
var head = this.Head;
head.Obj.Method(head.Obj);
}
}
interface ISeat
{
ISeat Child { get; set; }
Action<ISeat> Method { get; set; }
}