编辑
运行和调试后,我得出了这个结论 - 我仍然不知道问题的确切原因,但是它与表达式有关,此调用在执行时生成两种不同类型的表达式
当您使用
Func(new TypeA[] { new TypeA("value") });
它生成
。
{() => Invoke(Call(VarRef("obj"), value(Demo.Program+<>c__DisplayClass1).m.Name),new [] {new TypeA("value")})}
当你使用时
TypeA [] v = new TypeA[] { new TypeA("value") };
Func(v);
它生成
。
{() => Invoke(Call(VarRef("obj"), value(Demo.Program+<>c__DisplayClass1).m.Name),value(Demo.Program+<>c__DisplayClass1).v)}
注意区别。
new [] {new TypeA("value")}
vs
value(Demo.Program+<>c__DisplayClass1).v
其中,Demo是命名空间的名称,Program是类的名称,v是变量。
编辑2.2
为了更好地说明,我制作了这个示例应用程序。
using System;
using System.Linq.Expressions;
namespace TestXml
{
public class MyClass
{
public string Value { get; set; }
public MyClass(string value)
{
Value = value;
}
public override string ToString()
{
return Value;
}
}
class Program
{
static void Main(string[] args)
{
MyClass[] parameter = new MyClass[] { new MyClass("1") };
execute(() => TestInput( new MyClass[] { new MyClass("1") }));
execute(() => TestInput(parameter));
}
public static void TestInput(params object[] parameters)
{
if (parameters != null && parameters.Length > 0) Console.WriteLine(parameters.GetType().FullName);
}
public static void execute(Expression<Action> exp)
{
Console.WriteLine(exp);
}
public delegate void ParamsDelegate(params object[] param);
}
}
输出
() => TestInput(new [] {new MyClass("1")})
() => TestInput(value(TestXml.Program+<>c__DisplayClass0).parameter)
编辑3
为了知道行为差异的原因,我在MSDN上提出了问题,得到了以下答案:
"execute(() => TestInput( new MyClass[] { new MyClass("1") }));"
不会捕获任何东西,lambda表达式不使用任何变量。
"捕获指向参数变量的指针吗?"
我想你可以这么说。它实际上不是指针,而是将变量参数存储在对象字段中,而不是存储在堆栈中,你看到的c__DisplayClass0是编译器生成的类,用于保存参数变量
这表明这主要是LinqToCodeDom评估表达式时存在的一个bug,似乎他们没有处理这种情况。
Func(...)
的重载存在吗?接受params
参数的重载可能会导致这种混淆。 - Drew Noakes