c# - 引用委托类型
问题描述
为什么这个程序使用seq会报错:
class Program
{
delegate double Sequence(int r);
void F(ref Sequence seq) // Here
{
Sequence seq2 = r =>
{
if (r % 2 == 0)
return seq(r); // Here
else
return seq(2 * r); // Here
};
seq = seq2;
}
static void Main()
{
}
}
错误 CS1628 无法在匿名方法、lambda 表达式、查询表达式或本地函数 CsharpRefLambdaTest 内使用 ref、out 或 in 参数“seq”
问题在于参数seq
是引用类型。但是为什么错了?参考有什么问题seq
?如果seq
不是引用,则程序没有错误。
有没有办法在保持 seq 作为参考的同时更正程序?
该程序只是一个测试,它不会做任何事情。
=================
我需要使用 的值seq
来定义一个新的序列seq2
,然后赋值seq = seq2
。但是 seq 的值是不可用的。如果 的值seq
不可用,为什么 C# 允许seq
作为参考?
================================
编辑:
上面的程序只是以下程序的简化版本:
class Program
{
delegate double Sequence(int r);
Sequence G(Sequence seq)
{
Sequence seq2 = r =>
{
if (r % 2 == 0)
return seq(r);
else
return seq(2 * r);
};
return seq2;
}
void F(ref Sequence seq)
{
seq = G(seq);
}
static void Main()
{
}
}
但我不明白为什么我不能删除G
而是添加G inside
F` 的定义代码。
解决方案
这里的错误消息是:“CS1628 不能在匿名方法、lambda 表达式、查询表达式或本地函数中使用 ref、out 或 in 参数 'seq'” -seq2
是 lambda 表达式;它与引用类型无关,而是:生命周期。毕竟,你可以这样称呼它:
void Foo() {
Sequence bar = SomeMethod; // bar is a LOCAL of Foo
F(ref bar);
// not shown: perhaps do something with bar, perhaps not
}
此时,F
需要以某种方式创建一个 lambda,其中包含对堆栈上位置的引用(对 local 的引用bar
)。现在请注意,这个 lambda 作为一个对象,可能比它的寿命更长Foo
,并且bar
可能是一个未定义的 - 并且可能被重用的 - 内存位置。
所以:你不能“捕获”作为ref
, in
our传递的参数,out
我在这里松散地使用“捕获”来表示“在形成表达式树、委托表达式的 lambda 或匿名方法的范围内使用;或在迭代器块或异步延续中”。
只需删除ref
. 你不需要它,它没有帮助。如果您的意图是更改委托,则考虑改为返回组合委托。
作为替代解决方法:对值进行快照并捕获快照:
void F(ref Sequence seq)
{
var tmp = seq;
seq = r =>
{
if (r % 2 == 0)
return tmp(r);
else
return tmp(2 * r);
};
}
这避免了有问题的场景,因为快照取消了对参数的引用ref
,这意味着:现在我们不可能捕获堆栈位置。
推荐阅读
- node.js - Mongodb查询中maxDistance的默认单位是什么
- python - 在熊猫的两行之间划分值
- javascript - GroupBy 对象数组 JavaScript
- batch-file - 通过脚本启用本地组策略
- flutter - 无法使用颤振零安全颤振依赖项进行调试
- javascript - 为什么我无法在文档上设置 innerHTML?
- python - 如何正确地将 ComboBox 的模型从 python (pyQt5) 传递给 QML?
- excel - 识别公式中的第一个排序列
- python - 提取 pdf 文件的元数据(尺寸或方向)
- python - 我编写了根据日期将数据从较小数据帧复制到较大数据帧的代码,但速度很慢