在之前更新的文章中,有一篇C#的文章中,出现了两个比较类似的方法,C#学习随笔—自定义控件(线,箭头等图形)。我突然意识到,这一块完全可以用委托和Lambda表达式达成更加简洁的写法,同时,将这两个概念也分享一下,或许,大家在平时也会用到。
大概说一下,我的方法实现的功能。已经Start和End点的坐标,以及Offset的值,求解A点的坐标。见下图:
我之前文章中的代码如下:
//get x value of triangle
private float tri_x_value(float start_x, float start_y, float end_x, float end_y,float edge )
{
float value;
try
{
value=edge * (end_x - start_x) /(float)System.Math.Sqrt( ((end_x - start_x) * (end_x - start_x) + (end_y - start_y) * (end_y - start_y)));
}
catch
{
value=0;
}
return value;
}
//get y value of triangle
private float tri_y_value(float start_x, float start_y, float end_x, float end_y, float edge)
{
float value;
try
{
value=edge * (end_y - start_y) / (float)System.Math.Sqrt(((end_x - start_x) * (end_x - start_x) + (end_y - start_y) * (end_y - start_y)));
}
catch
{
value=10;
}
return value;
}
基本原理,就是勾股定理以及三角函数一些知识,大家可以对比两个方法,这两个方法分别为了求取A点坐标的x和y。这两个函数其实有很大的类似点儿,主要是核心算式中的不同,分母相同,其中一个分子不同,如下:
//x坐标
value=edge * (end_x - start_x) / (float)System.Math.Sqrt(((end_x - start_x) * (end_x - start_x) + (end_y - start_y) * (end_y - start_y)));
//y坐标
value=edge * (end_y - start_y) / (float)System.Math.Sqrt(((end_x - start_x) * (end_x - start_x) + (end_y - start_y) * (end_y - start_y)));
那么,我们是否可以将其合并为一个方法呢?当然是可以的,这个时候就用到了大专委托的概念,了解C语言的朋友们,可以这样理解,委托其实类似C语言的函数指针,都是可以调用函数或者方法的。
因此,我们可以对上述函数简化为:
delegate float get_tri_value_t(float start_x,float start_y,float end_x,float end_y);
private float tri_value(float start_x, float start_y, float end_x, float end_y,float edge,get_tri_value_t method)
{
float value;
try
{
value=edge /(float)System.Math.Sqrt( ((end_x - start_x) * (end_x - start_x) + (end_y - start_y) * (end_y - start_y)));
value=method(start_x,start_y,end_x,end_y)*value;
}
catch
{
value=0;
}
return value;
}
如上述所示,定义了委托get_tri_value_t,该委托只要计算两个值的差值即可,x或者y坐标。然后在tri_value方法中调用该委托即可。委托需要指定特定的方法,要得到x坐标就指向x的方法,要得到y坐标,那么就要指向y的方法。如下图所示:
private float cal_x_value(float start_x, float start_y, float end_x, float end_y)
{
return end_x - start_x;
}
private float cal_y_value(float start_x, float start_y, float end_x, float end_y)
{
return end_y - start_y;
}
public SimplyCtrlLine()
{
get_tri_value_t get_tri_value=cal_x_value;//指定该委托为得到一个x坐标
//get_tri_value_t get_tri_value=cal_y_value;//指定该委托为得到一个y坐标
tri_value(a,b,c,d,get_tri_value)
}
上面就是一个完整的委托。如果只是上面的情况,其实对于代码的简化还是非常有限的。因此我们引入了Lambda表达式。
Lambda表达式的格式为:(input-parameters)=> { }。任何 Lambda 表达式都可以转换为委托类型。 Lambda 表达式可以转换的委托类型由其参数和返回值的类型定义。因此Lambda表达式的本质就是委托,只是为了简化代码。
因此,上述代码就可以简化如下:
delegate float get_tri_value_t(float start_x,float start_y,float end_x,float end_y);
private float tri_value(float start_x, float start_y, float end_x, float end_y,float edge,get_tri_value_t method)
{
float value;
try
{
value=edge /(float)System.Math.Sqrt( ((end_x - start_x) * (end_x - start_x) + (end_y - start_y) * (end_y - start_y)));
value=method(start_x,start_y,end_x,end_y)*value;
}
catch
{
value=0;
}
return value;
}
public SimplyCtrlLine()
{
tri_value(a,b,c,d,(a,b,c,d)=>{return c-a});
//tri_value(a,b,c,d,(a,b,c,d)=>{return d-b});
}
看最后调用的该方法时的简化,可以看出来,用Lambda表达式可以省去很多方法的定义。写法上非常简化。
上面就是本文分享的内容,也是无意间想到的一个比较实用的应用点。希望对大家有帮助。另外,我有一篇文章是关于多线程UI控制的,这个也是用到了委托,大家如果觉得以后会用到,也可以看看。