你能把一个函数传递给一个类吗[重复]

问题描述 投票:0回答:2

我为控制台应用程序创建了一个菜单选项类,并希望将执行方法绑定到该选项,这样当用户做出选择时,我可以执行类似 selectedOption.Execute() 的操作。该选项的执行方法将绑定到实用程序类中的适当方法。这可能吗?这是我到目前为止所拥有的。

菜单选项类

public class MenuOption
{
    public MenuOption()
    {
    }

    public MenuOption(ConsoleKey key, string optionLabel, string optionText)
    {
        Key = key;
        OptionLabel = optionLabel;
        OptionText = optionText;
    }

    public MenuOption(ConsoleKey key, string optionLabel, string optionText, List<MenuOption> subMenu)
    {
        Key = key;
        OptionLabel = optionLabel;
        OptionText = optionText;
        SubMenu = subMenu;
    }
    public ConsoleKey? Key { get; set; } = null;
    public string OptionLabel { get; set; } = string.Empty;
    public string OptionText { get; set; } = string.Empty;
    public List<MenuOption> SubMenu { get; set; } = new List<MenuOption>();
    public string Display()
    {
        StringBuilder menu = new StringBuilder();
        menu.AppendLine("Press the number associated with the option of your choice or [Esc] to exit.");
        foreach (MenuOption option in SubMenu)
        {
            if (option.Key == ConsoleKey.Escape)
            {
                menu.AppendLine($"{option.OptionLabel} {option.OptionText}");
            }
            else
            {
                menu.AppendLine($"{option.OptionLabel}. {option.OptionText}");
            }
        }
        return menu.ToString();
    }
}
c# console-application .net-7.0
2个回答
1
投票

是的,您可以使用委托或 Action(它是委托,但由 C# 提供,因此您不必声明)来做到这一点。你可以查看如何使用委托,但我会在这里使用

Actions

  1. 为代表执行方法的
    Action
    类添加一个
    MenuOption
    属性
  2. 修改构造函数以接受执行方法作为参数。

例如

using System;
using System.Collections.Generic;
using System.Text;

public class MenuOption
{
    public MenuOption() { }

    public MenuOption(ConsoleKey key, string optionLabel, string optionText, Action action)
    {
        Key = key;
        OptionLabel = optionLabel;
        OptionText = optionText;
        Action = action;
    }

    public MenuOption(ConsoleKey key, string optionLabel, string optionText, List<MenuOption> subMenu, Action action)
    {
        Key = key;
        OptionLabel = optionLabel;
        OptionText = optionText;
        SubMenu = subMenu;
        Action = action;
    }

    public ConsoleKey? Key { get; set; } = null;
    public string OptionLabel { get; set; } = string.Empty;
    public string OptionText { get; set; } = string.Empty;
    public List<MenuOption> SubMenu { get; set; } = new List<MenuOption>();

    // Action property to represent the execution method
    public Action Action { get; set; }

    public string Display()
    {
        var menu = new StringBuilder();
        menu.AppendLine("Press the number associated with the option of your choice or [Esc] to exit.");
        
        foreach (var option in SubMenu)
        {
            menu.AppendLine(option.Key == ConsoleKey.Escape
                ? $"{option.OptionLabel} {option.OptionText}"
                : $"{option.OptionLabel}. {option.OptionText}");
        }
        
        return menu.ToString();
    }

    // Execute method to call the bound action
    public void Execute()
    {
        Action?.Invoke();
    }
}

至于如何使用它,它看起来像这样:

MenuOption option1 = new MenuOption(ConsoleKey.A, "A", "Option 1", UtilityClass.SomeMethod);

注意

UtilityClass.SomeMethod
没有
()
因为我们没有执行方法,我们只是将指针传递给函数。

如果需要,您也可以使用 Lambda(匿名函数)。

MenuOption option1 = new MenuOption(ConsoleKey.A, "A", "Option 1", () => Console.WriteLine("Option 1 selected"));

0
投票

A delegate 是一种类型,表示对具有特定参数列表和返回类型的方法的引用。委托用于将方法作为参数传递给其他方法。来自与委托类型匹配的任何可访问类或结构的任何方法都可以分配给委托。

比如ActionDelegate封装了一个无参数不返回值的方法

.net 有一个针对不同代表的特殊类型

  1. Func
    委托接受零个、一个或多个输入参数,并返回一个值(及其输出参数)。
  2. Action
    接受零个、一个或多个输入参数,但不返回任何内容。
  3. Predicate
    是一种特殊的
    Func
    。它表示一种方法,该方法包含一组主要在 if 条件内定义的条件,并检查传递的参数是否满足这些条件。

例如可以在

Action
类的构造函数中添加一个
MenuOption
类型的参数,在需要的地方调用它

public class MenuOption
{
    public MenuOption()
    {
    }

    public MenuOption(ConsoleKey key, string optionLabel, string optionText, Action execute)
    {
        Key = key;
        OptionLabel = optionLabel;
        OptionText = optionText;
        Execute = execute;
    }

    public MenuOption(ConsoleKey key, string optionLabel, string optionText, List<MenuOption> subMenu, Action execute)
    {
        Key = key;
        OptionLabel = optionLabel;
        OptionText = optionText;
        SubMenu = subMenu;
        Execute = execute;
    }

    public ConsoleKey? Key { get; set; } = null;
    public string OptionLabel { get; set; } = string.Empty;
    public string OptionText { get; set; } = string.Empty;
    public List<MenuOption> SubMenu { get; set; } = new List<MenuOption>();
    public Action Execute { get; set; }

    public string Display()
    {
        // ...
    }
}

这里是创建一个带有

MenuOption
参数的
Action
的例子。你可以像一个简单的方法一样调用动作:

var option = new MenuOption(ConsoleKey.A, "A", "Print text", () => Console.WriteLine("Hello world"));
option.Execute(); // Execute property is public and has Action type so you can call it without parameters

您还可以将现有方法添加为参数:

public class Utility
{
    public static void MyMethod()
    {
        Console.WriteLine("Hello from MyMethod!");
    }
}

class Program
{
    static void Main(string[] args)
    {
        var option = new MenuOption(ConsoleKey.A, "A", "Execute MyMethod", Utility.MyMethod);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.