如何在C#中声明带Action<T>参数的构造函数(类似C语言中传递函数指针)
解决Error CS0236:字段初始值设定项无法引用非静态成员的问题
这个错误我之前也踩过坑,核心原因其实很明确:字段初始化代码是在类的构造函数执行前运行的,这时候你的Form1实例还没完全创建出来,Log作为实例方法(非静态),此时还没法被引用——编译器没法确定这个方法属于哪个具体的Form1对象,自然就报错了。
最直接的修复方法:把MyClass的初始化移到构造函数里
把字段声明和初始化分开,在Form1的构造函数里完成Class1的实例化就行。这时候实例已经创建完成,Log方法可以正常被引用:
public partial class Form1 : Form { Class1 MyClass; // 先声明字段,暂不初始化 public Form1() { InitializeComponent(); MyClass = new Class1(Log); // 这里实例已就绪,完全没问题 } public void Log(string line) { rtb.Text += line + "\n"; } // ... }
为啥编译器明明知道Log存在却报错?
你说的没错,Action<string>确实对应返回void、带string参数的委托,但C#的字段初始化时机是在实例构造之前,此时this(当前Form1实例)还未完全初始化,语言设计上禁止在这个阶段引用实例成员——这是个安全约束,防止引用未初始化的对象状态。
另一种可选方案:用Lambda表达式简化(按需选择)
如果不想单独写Log方法,也可以用Lambda表达式直接把日志逻辑传进去,不过本质上还是依赖实例初始化后的状态,所以依然建议放在构造函数里InitializeComponent()之后,避免rtb还没创建就被调用:
public partial class Form1 : Form { Class1 MyClass; public Form1() { InitializeComponent(); // 直接把日志逻辑写在Lambda里,不用单独定义Log方法 MyClass = new Class1(line => rtb.Text += line + "\n"); } // ... }
这样既满足了你传递“函数指针”(在C#里就是委托)的需求,又避开了字段初始化的限制。
内容的提问来源于stack exchange,提问作者yo3hcv
相关产品推荐
相关产品推荐

