You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 04:47:31