感谢 这个问题的答案 当我将类扩展为匿名类型时,我能够重写 C# 中的虚拟方法。
但是是否可以引用祖先类的类变量或属性?
这是我的 C# 代码的简化版本:
public class MyAsyncBackgroundJob<TExecuteArgs> {
public Func<TExecuteArgs, Task> ExecutePropAsync { get; set; }
protected int _myVariable = 1; // just an example
public int MyProp { get; set; } = 2; // just an example
public MyAsyncBackgroundJob() {
}
public override Task ExecuteAsync(TExecuteArgs args) {
return ExecutePropAsync(args);
}
}
以及我想如何使用它:
var anonymous = new MyAsyncBackgroundJob<string> {
ExecutePropAsync = (string s) => {
string output = null;
// this example works:
if (s == "example") output = s + s;
// this example DOESN'T works:
if (_myVariable == 1) output = s + s;
// this example DOESN'T works:
if (MyProp == 1) output = s + s;
return Task.FromResult(output);
}
};
// Note: in the real life ExecuteAsync(TExecuteArgs args) is called automatically by the framework
await anonymous.ExecutePropAsync("example");
注意:在现实生活中
ExecuteAsync(TExecuteArgs args)
是由框架自动调用的
首先你错了。变量
anonymous
不是匿名的,它是强类型的 MyAsyncBackgroundJob<string>
,但 lambda 表达式确实会生成匿名类型。
您的问题是因为您尝试在 lambda 表达式的范围内引用
MyAsyncBackgroundJob<string>
的属性,与类定义的范围内不同,该范围内没有隐式 this
对象,您必须提供引用像obj.MyProp
这样的物体。
但是当你像这样使用对象初始化器时:
var obj = new MyAsyncBackgroundJob<string>{}
,实际上,这个变量obj
只会在对象初始化器完成后才会被赋值,所以你无法在lambda表达式中访问它。您可以预先初始化它。
MyAsyncBackgroundJob<string> job = null;
job = new MyAsyncBackgroundJob<string> {
ExecutePropAsync = (string s) => {
string output = null;
// this example works:
if (s == "example") output = s + s;
// this example DOESN'T works:
//if (job._myVariable == 1) output = s + s;
if (job.MyProp == 1) output = s + s;
return Task.FromResult(output);
}
};
但是,无论如何,
job._myVariable
都不起作用,因为您无法访问类定义范围之外的受保护字段/属性。
可以给
ExecutePropAsync
添加一个额外的参数,这样调用的时候就可以传递this
了。然后在使用站点,您可以通过该参数访问this
。
public Func<MyAsyncBackgroundJob<TExecuteArgs>, TExecuteArgs, Task> ExecutePropAsync { get; init; }
public Task ExecuteAsync(TExecuteArgs args) {
return ExecutePropAsync(this, args);
}
现在可以编译了:
var job = new MyAsyncBackgroundJob<string> {
ExecutePropAsync = (self, s) => {
string output = null;
if (s == "example") output = s + s;
if (self.MyProp == 1) output = s + s;
return Task.FromResult(output);
}
};
但是,这种方法不允许您访问受保护的成员。毕竟,您分配给
ExecutePropAsync
的 lambda 不在 MyAsyncBackgroundJob
或其任何子类中。
虽然您也可以以相同的方式将所需的受保护属性作为 lambda 的参数传递(也许可以先将它们包装在另一个类中,如果有很多),但我个人此时会创建
MyAsyncBackgroundJob
的子类,哪个更易于维护。否则,每次在 MyAsyncBackgroundJob
中添加受保护成员时,都必须更新包装类中的 lambda 参数/属性。