C#实例化类时如何引用父类的变量与属性?
问题描述
我已经能在C#中通过类似匿名类的方式扩展类并重写虚方法,但现在遇到一个问题:在这种场景下无法引用父类的类变量或属性。
简化后的父类代码:
public class MyAsyncBackgroundJob<TExecuteArgs> { public Func<TExecuteArgs, Task> ExecutePropAsync { get; set; } protected int _myVariable = 1; // 示例变量 public int MyProp { get; set; } = 2; // 示例属性 public MyAsyncBackgroundJob() { } public virtual Task ExecuteAsync(TExecuteArgs args) { return ExecutePropAsync(args); } }
我期望的使用方式:
var myVar = new MyAsyncBackgroundJob<string> { ExecutePropAsync = (string s) => { string output = null; // 这段代码正常工作 if (s == "example") output = s + s; // 编译报错:找不到_myVariable if (_myVariable == 1) output = s + s; // 编译报错:找不到MyProp if (MyProp == 1) output = s + s; return Task.FromResult(output); } }; // 实际场景中ExecuteAsync会被框架自动调用 await myVar.ExecutePropAsync("example");
当前代码无法访问父类的_myVariable和MyProp,编译器提示未找到这些成员,求解决方法。
解决方法
方案1:捕获实例引用
放弃对象初始化器,先创建实例再给委托赋值,同时捕获实例本身,通过实例访问父类成员:
var myVar = new MyAsyncBackgroundJob<string>(); myVar.ExecutePropAsync = s => { string output = null; // 通过实例访问父类成员 if (myVar._myVariable == 1) output = s + s; if (myVar.MyProp == 1) output = s + s; return Task.FromResult(output); };
注意:对象初始化器执行时实例尚未完全初始化,无法直接在初始化器内引用自身,因此必须拆分创建和赋值步骤。
方案2:修改父类委托定义,传入实例参数
调整父类中ExecutePropAsync的委托类型,增加当前实例作为参数,在委托中通过该参数访问成员:
public class MyAsyncBackgroundJob<TExecuteArgs> { // 调整委托,增加当前实例参数 public Func<MyAsyncBackgroundJob<TExecuteArgs>, TExecuteArgs, Task> ExecutePropAsync { get; set; } protected int _myVariable = 1; public int MyProp { get; set; } = 2; public virtual Task ExecuteAsync(TExecuteArgs args) { // 调用委托时传入当前实例 return ExecutePropAsync(this, args); } }
使用时通过第一个参数访问实例成员:
var myVar = new MyAsyncBackgroundJob<string> { ExecutePropAsync = (job, s) => { string output = null; if (job._myVariable == 1) output = s + s; if (job.MyProp == 1) output = s + s; return Task.FromResult(output); } };
方案3:直接重写虚方法(替代委托方案)
如果核心需求是重写ExecuteAsync方法,直接用子类重写的方式,能自然访问父类成员,无需依赖委托:
// C# 10+支持局部类,避免污染全局命名空间 file class TempBackgroundJob : MyAsyncBackgroundJob<string> { public override Task ExecuteAsync(string args) { string output = null; // 直接访问父类成员 if (_myVariable == 1) output = args + args; if (MyProp == 3) output = args + args; return Task.FromResult(output); } } var myVar = new TempBackgroundJob { MyProp = 3 };
这种方式既满足类似匿名类的临时扩展需求,又能正常访问父类的变量和属性。
内容的提问来源于stack exchange,提问作者Gianpiero
相关产品推荐
相关产品推荐

