参考代表类型
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了参考代表类型相关的知识,希望对你有一定的参考价值。
为什么这个程序显示使用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或参数'seq'
问题在于参数seq
是引用类型。但为什么这是错的?参考seq
有什么问题?如果seq
不是引用,程序没有错误。
有没有办法纠正程序,同时保持seq作为参考?
该计划只是一个测试,它不会做任何事情。
================
我需要使用seq
的值来定义一个新的Sequence 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或参数'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,其中包含对堆栈中位置的引用(对本地bar
的引用)。现在请注意,作为对象的这个lambda可以比Foo
更长,而bar
将是一个未定义的 - 并且可能重用 - 内存位置。
所以:你不能“捕获”作为ref
传递的参数,in
我们的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
参数,这意味着:现在我们不可能捕获堆栈位置。
以上是关于参考代表类型的主要内容,如果未能解决你的问题,请参考以下文章