如何为含Action<T>属性的类声明接收带参数方法的构造函数?
原始问题
我想要实现一个MenuItem类,让其中的Method属性能接收特定类型的参数,该参数可通过构造函数传入,后续在其他类或第三方方法中调用。但尝试的代码无法运行,想确认使用Action<T>是否是正确的实现方向。
原始错误代码:
public class MenuItem { public string Title { get; set; } = ""; public Action? Method(<T> x) { get; set; } = null; public MenuItem(string title,Action Method(<T> x) { Title = title; Method = Method(<T> x) } }
补充代码与错误
尝试修正后,IDE提示类型转换错误,相关代码如下:
public static void CallGUI() { RepoController controller = new RepoController(); Menu lager = new Menu("WELCOME"); lager.MenuItems.Add(lager.DictTKey, newMenuItem("MENU", CreateNewProductItem(controller))); } public class Menu { public string Title { get; set; } = ""; public int DictTKey { get; set; } = 0; public Dictionary<int,MenuItem> MenuItems { get; set; } = new Dictionary<int,MenuItem>(); public Menu(string title) { Title = title; } public void AddMenuItem(string title,Action<RepoController> method) { MenuItems.Add(++DictTKey, new MenuItem(title, method)); } } public class MenuItem { public string Title { get; set; } = ""; public Action<RepoController>? Method { get; set; } = null; public MenuItem(string title,Action<RepoController> method) { Title = title; Method = method; } }
报错信息:
CS1503: Argument 2: cannot convert from 'void' to System.Action
解决方案
1. 原始问题的语法修正
使用Action<T>是正确的实现方向,但你的语法存在错误:
- 正确的属性声明应为
public Action<T>? Method { get; set; },而非带参数括号的写法 - 如果要让
MenuItem支持任意类型,需将其定义为泛型类:
public class MenuItem<T> { public string Title { get; set; } = ""; public Action<T>? Method { get; set; } = null; public MenuItem(string title, Action<T>? method = null) { Title = title; Method = method; } }
创建实例时指定类型即可:new MenuItem<RepoController>("标题", 目标方法)
2. 补充代码的类型转换错误修复
报错的核心原因是:你传递的CreateNewProductItem(controller)是方法执行后的结果(返回void),但MenuItem构造函数需要的是方法的委托引用(Action<RepoController>类型)。
修正方式有两种:
方式1:直接传递方法引用(要求方法签名匹配Action<RepoController>)
public static void CallGUI() { RepoController controller = new RepoController(); Menu lager = new Menu("WELCOME"); // 注意修正newMenuItem为new MenuItem lager.MenuItems.Add(lager.DictTKey, new MenuItem("MENU", CreateNewProductItem)); }
方式2:使用Lambda表达式包装(更灵活,适配复杂场景)
public static void CallGUI() { RepoController controller = new RepoController(); Menu lager = new Menu("WELCOME"); lager.MenuItems.Add(lager.DictTKey, new MenuItem("MENU", c => CreateNewProductItem(c))); // 推荐使用Menu类提供的AddMenuItem方法,避免手动维护DictTKey lager.AddMenuItem("MENU", CreateNewProductItem); }
内容的提问来源于stack exchange,提问作者Aleksandar
相关产品推荐
相关产品推荐

