Previous topicNext topic
Help > 开发指南 > 编程基础 > 常用概念 >
匿名方法

概念

匿名方法:没有名字的方法,不需要名字的方法。

匿名方法是没有名称只有主体的方法。

匿名方法和委托搭载使用。

匿名方法 精确点可以改叫 匿名函数。

委托是用于引用与其具有相同标签的方法。换句话说,您可以使用委托对象调用可由委托引用的方法。

匿名方法(Anonymous methods) 提供了一种传递代码块作为委托参数的技术。

在匿名方法中您不需要指定返回类型,它是从方法主体内的 return 语句推断的。

使用场景

1. delegate 委托匿名方法

C#
//委托
delegate int CalcuteSum(int num1,int num2);

static void ObjectTest1()
{
    //委托匿名方法1
    CalcuteSum calcuate1 = delegate (int num1, int num2)
    {

        return num1 + num2;
    };

    int result = calcuate1(1, 2);
    Console.WriteLine(result);//3

    //委托匿名方法1
    calcuate1 = delegate (int num1, int num2)
    {
        return num1 + num2 + 1;
    };


    int result2 = calcuate1(1, 2);
    Console.WriteLine(result2);//4

    //委托静态方法
    calcuate1 = TestSum;
    int result3 = TestSum(1, 2);
    Console.WriteLine(result3);//5
}

static int TestSum(int num1, int num2)
{
    return num1 + 1 + num2 + 1;
}

2. 匿名方法 和  Lamda表达式

   从 C# 3 开始,lambda 表达式提供了一种更简洁和富有表现力的方式来创建匿名函数。 使用 => 运算符构造 lambda 表达式:

< /TABLE >
3.方便开发和使用的委托  Action,Func

Action: 没有返回类型的委托定义。

C#
Func<int, int, int> sum = (a, b) => a + b;
Console.WriteLine(sum(3, 4));  // output: 7
C#
Action greet = delegate { Console.WriteLine("Hello!"); };
greet();
Action<int, int> getNum = delegate (int num1, int num2)
{
    var result = num1 * num2;
 
    Console.WriteLine(result);
};

Func :需要返回类型的委托定义。

C#
Func<int, int, int> sum = static delegate (int a, int b) { return a + b; };
Console.WriteLine(sum(10, 4));  // output: 14

以上内容转自:(5条消息) C# 匿名函数_C# 匿名函数使用整理_天马3798的博客-CSDN博客

我们为什么需要学习这个匿名方法呢?因为我们在写全局表事件、全局项目事件、内部函数时,如果我们需要动态绑定一些控件的事件的话,就不像窗体事件以及表事件中那么方便了。这些事件代码只有一个方法体,我们想要绑定事件的话只有两种方法,一种是匿名方法,另外一种就是将控件的事件写到全局代码里面,然后再引用。

下面我们就以表事件BeforeShowContextMenu中的示例,将之转化,改写到全局表事件中,看看应该如何修改。

全局代码,因为Vb.net不支持匿名绑定事件,就只能在全局代码中写入菜单的单击事件代码了。注意:Vb.net在全局代码中创建一个MainModule的Module,而不是普通的Class。主要是为了方便在其他地方直接引用。

Vb.Net
Namespace UserClass
    Public Module MainModule
        Public Sub menuCommand_Click(ByVal senderSub As System.Object, ByVal eSub As C1.Win.C1Command.ClickEventArgs)
             Dim cmdSub As SmCommand = CType(senderSub, SmCommand)
             Dim lnkSub As sanMuSoft.CS.WinForm.Controls.SmCommandLink = CType(eSub.CallerLink, sanMuSoft.CS.WinForm.Controls.SmCommandLink)
             MessageBox.Show(String.Format("当前菜单命令的文本为:{0},当前命令的名称为:{1}", lnkSub.Text, cmdSub.Name))
        End Sub
    End Module
End Namespace

Vb.Net
'获得对表的引用
Dim tblMain As BaseGrid=sender
Select Case e.HitType
    Case HitTestTypeEnum.RowHeader
        e.ContextMenu = Proj.GridContextMenu("选择区域右键菜单")
        Exit Select
    Case HitTestTypeEnum.ColumnHeader
        '判断
        If Proj.FormTags.ExtendedProperties(tblMain.Form.Name,tblMain.Name).ContainsKey("m_haveAddColumnMenu")=False OrElse Proj.FormTags.ExtendedProperties(tblMain.Form.Name,tblMain.Name)("m_haveAddColumnMenu") = False Then
            Dim lnk As SmCommandLink = New SmCommandLink()
            lnk.Name = "lnkTestMenu"
            lnk.Text = "插入右键菜单"
            lnk.Delimiter = True
            lnk.ToolTipText = "这是插入右键菜单的提示信息"
            Dim cmd As SmCommand = New SmCommand()
            cmd.Name = "cmdTestMenu"
            cmd.Text = "插入右键菜单"
            cmd.ToolTipText = "命令中设置的ToolTipText"
            cmd.Image = Sys.GetImage("accept_16x16.png", Path.Combine(Proj.ApplicationPath, "Images"))
            '绑定全局代码中菜单的Click事件
            AddHandler cmd.Click,AddressOf UserClass.MainModule.menuCommand_Click
            lnk.Command = cmd
            e.ContextMenu.CommandLinks.Add(lnk)
            Proj.FormTags.ExtendedProperties(tblMain.Form.Name,tblMain.Name)("m_haveAddColumnMenu") = True
        End If

        Exit Select
    Case Else
        e.Cancel = True
        Exit Select
End Select

 

C#
BaseGrid tblMain=sender as BaseGrid;
switch (e.HitType)
{
    case HitTestTypeEnum.RowHeader:
    {
        // 如果是行标题,直接用自定义菜单代替
        e.ContextMenu = Proj.GridContextMenu["选择区域右键菜单"];
        break;
    }
    
    case HitTestTypeEnum.ColumnHeader:
    {
        // 这里可以单独地添加一个或多个自定义菜单
        if (Proj.FormTags.ExtendedProperties(tblMain.Form.Name,tblMain.Name)["m_haveAddColumnMenu"].CType<bool>(false) == false) //如果没有添加过菜单就添加,添加过了就不再重复添加了
        {
            SmCommandLink lnk = new SmCommandLink();
            lnk.Name = "lnkTestMenu";
            // 命令菜单上显示的文本
            lnk.Text = "插入右键菜单";
            // 是否显示分隔符
            lnk.Delimiter = true;
            // 鼠标移动到此菜单上时会提示出来的信息
            lnk.ToolTipText = "这是插入右键菜单的提示信息";
            SmCommand cmd = new SmCommand();
            cmd.Name = "cmdTestMenu";
            cmd.Text = "插入右键菜单";
            cmd.ToolTipText = "命令中设置的ToolTipText";
            // 设置命令的图标
            cmd.Image = Sys.GetImage("accept_16x16.png", Path.Combine(Proj.ApplicationPath, "Images"));
            // 绑定命令的单击事件
            cmd.Click += (System.Object senderSub, C1.Win.C1Command.ClickEventArgs eSub)=>
            {
                // 获得对命令的引用
                SmCommand cmdSub = (SmCommand)senderSub;
                // 获得对SmCommandLink的引用
                sanMuSoft.CS.WinForm.Controls.SmCommandLink lnkSub = (sanMuSoft.CS.WinForm.Controls.SmCommandLink)eSub.CallerLink;
                MessageBox.Show(string.Format("当前菜单命令的文本为:{0},当前命令的名称为:{1}", lnkSub.Text, cmdSub.Name));
            };
            // 将命令引用到菜单链接里面
            lnk.Command = cmd;
            // 将菜单链接添加到系统默认菜单里面
            e.ContextMenu.CommandLinks.Add(lnk);
            Proj.FormTags.ExtendedProperties(tblMain.Form.Name,tblMain.Name)["m_haveAddColumnMenu"] = true;
        }
        
        break;
    }
    
    default:
    {
        // 如果是其他部位的右键菜单,一律禁用
        e.Cancel = true;
        break;
    }
}

上面的代码转换涉及到两个主要的知识点。

1、逻辑类型私有字段m_haveAddColumnMenu的转换。

因为在常规的表事件或者在窗体事件中,我们设置的私有字段的生效范围只有那一个窗体或者一个表中可访问。然后我们现在将代码转换到全局表事件当中时,作判断的话就必须将变量的维度拉到指定窗体、指定表对应的m_haveAddColumnMenu变量上,要不然就简单的设置一个Var变量的话,就会导致所有表事件只有第一个表触发时会执行此代码,然后其他表都因为这个变量而无法继续执行。

所以我们使用Proj.FormTags.ExtendedProperties这种支持三维的变量(详细介绍可参考:如何传递共享变量)的方法。

2、匿名方法的使用。

我们在使用匿名方法时,输入参数中的参数名不能与主方法中的e参数重名,需要进行改名称。由于匿名函数是允许直接访问事件中定义的局部变量的,所以在匿名函数里面使用的变量也要避免与局部变量重名。