我的问题是,我无法在c#表达式树(例如System.Linq.Expressions)中使用块来获取局部变量,而不会抛出异常,尽管函数参数变量工作得很好。
通过'局部变量'在这里,我不是指关闭。我指的是c#表达式树中特定于块的本地变量。目前,我有一个非常奇怪的情况,一个表达式树工作,另一个抛出异常:
未处理的类型' System.InvalidOperationException'发生在System.Core.dll
中附加信息:变量' num'类型' System.Int32'引用范围'',但未定义
工作代码编译自:
public static int Assign ()
{
int num;
int num2;
num = 1;
num2 = 2;
return num + num2;
}
到表达式树(调试视图):
.Lambda #Lambda1<System.Func`1[System.Int32]>() {
.Block(
System.Int32 $num,
System.Int32 $num2) {
0;
0;
$num = 1;
$num2 = 2;
.Return returnLabel { $num + $num2 };
.Label
0
.LabelTarget returnLabel:
}
}
这正常。但是,当我的编译器尝试编译它时:
public static int Assign ()
{
int num = 1;
int num2 = 2;
return num + num2;
}
为:
.Lambda #Lambda1<System.Func`1[System.Int32]>() {
.Block(
System.Int32 $num,
System.Int32 $num2) {
$num = 1;
$num2 = 2;
.Return returnLabel { $num + $num2 };
.Label
0
.LabelTarget returnLabel:
}
}
此块表达式抛出无效操作异常 -
未处理的类型&#39; System.InvalidOperationException&#39;发生在System.Core.dll中 附加信息:变量&#39; num&#39;类型&#39; System.Int32&#39;引用范围&#39;&#39;,但未定义
这里真正令人困惑的是,唯一的区别是由随机{0} - System.Linq.Expressions.Expression.Constant(0)表达式引起的,似乎使错误消失(这些存在的原因是
具体而言,对于lambda中定义的参数,此问题不会出现 表达式,例如,编译器处理:
public static Crappier<int> FieldAssign(int i, Crap thing)
{
thing.field = i;
return new Crappier<int>(); ;
}
精确输出表达式树:
.Lambda #Lambda1<System.Func`3[System.Int32,Sulieman.Crap,Sulieman.Crappier`1[System.Int32]]>(
System.Int32 $i,
Sulieman.Crap $thing) {
.Block() {
$thing.field = $i;
.Return returnLabel { .New Sulieman.Crappier`1[System.Int32]() };
.Label
null
.LabelTarget returnLabel:
}
}
但是,我特别想要绑定到一个块的变量。原因在于代码:
for (int i = 0; i < 3; i++) {
Console.WriteLine("hello");
}
for (int i = 0; i < 3; i++) {
Console.WriteLine("world");
}
这是有效的c#代码,因为虽然我被声明了两次,但它被声明为它 当地范围。我的编译器试图通过编译为:
来解释这个问题*.Lambda #Lambda1<System.Action>() {
.Block() {
.Block(System.Int32 $i) {
$i = 0;
.Loop .LabelTarget forContinueLabel: {
.If ($i < 3) {
.Block() {
.Block() {
.Call System.Console.WriteLine("hello")
};
$i++
}
} .Else {
.Break forBreakLabel { }
}
}
.LabelTarget forBreakLabel:
};
.Block(System.Int32 $i) {
$i = 0;
.Loop .LabelTarget forContinueLabel: {
.If ($i < 3) {
.Block() {
.Block() {
.Call System.Console.WriteLine("world")
};
$i++
}
} .Else {
.Break forBreakLabel { }
}
}
.LabelTarget forBreakLabel:
};
.Label
3
.LabelTarget returnLabel:
}
}
有关如何处理此事的任何建议?我确信我完全以错误的方式处理这些局部变量。
答案 0 :(得分:-1)
没关系 - 这是一个令人讨厌的错误,其中赋值$ num引用了一个不同的对象,但同名参数表达式与块中的参数表达式不同。具有相同名称的参数表达式不一定是相同的参数表达式!