我遇到了一个用于检查方法参数的实用程序类的问题。它使用dynamic
关键字作为泛型类型参数很多。有System.NullReferenceException
抛出,我不明白。
该异常具有以下堆栈跟踪:
(我为相当长的摘录道歉,但对我来说似乎有必要......)
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.ExpressionTreeCallRewriter.GenerateLambda(Microsoft.CSharp.RuntimeBinder.Semantics.EXPRCALL) Unknown
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.ExpressionTreeCallRewriter.VisitCALL(Microsoft.CSharp.RuntimeBinder.Semantics.EXPRCALL) Unknown
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.Semantics.ExprVisitorBase.Dispatch(Microsoft.CSharp.RuntimeBinder.Semantics.EXPR) Unknown
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.Semantics.ExprVisitorBase.Visit(Microsoft.CSharp.RuntimeBinder.Semantics.EXPR) Unknown
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.ExpressionTreeCallRewriter.Rewrite(Microsoft.CSharp.RuntimeBinder.Semantics.TypeManager, Microsoft.CSharp.RuntimeBinder.Semantics.EXPR, System.Collections.Generic.IEnumerable<System.Linq.Expressions.Expression>) Unknown
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.RuntimeBinder.CreateExpressionTreeFromResult(System.Collections.Generic.IEnumerable<System.Linq.Expressions.Expression>, Microsoft.CSharp.RuntimeBinder.RuntimeBinder.ArgumentObject[], Microsoft.CSharp.RuntimeBinder.Semantics.Scope, Microsoft.CSharp.RuntimeBinder.Semantics.EXPR) Unknown
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.RuntimeBinder.BindCore(System.Dynamic.DynamicMetaObjectBinder, System.Collections.Generic.IEnumerable<System.Linq.Expressions.Expression>, System.Dynamic.DynamicMetaObject[], out System.Dynamic.DynamicMetaObject) Unknown
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.RuntimeBinder.Bind(System.Dynamic.DynamicMetaObjectBinder, System.Collections.Generic.IEnumerable<System.Linq.Expressions.Expression>, System.Dynamic.DynamicMetaObject[], out System.Dynamic.DynamicMetaObject) Unknown
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.BinderHelper.Bind(System.Dynamic.DynamicMetaObjectBinder, Microsoft.CSharp.RuntimeBinder.RuntimeBinder, System.Collections.Generic.IEnumerable<System.Dynamic.DynamicMetaObject>, System.Collections.Generic.IEnumerable<Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo>, System.Dynamic.DynamicMetaObject) Unknown
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.CSharpConvertBinder.FallbackConvert(System.Dynamic.DynamicMetaObject, System.Dynamic.DynamicMetaObject) Unknown
System.Dynamic.Runtime.dll!System.Dynamic.ConvertBinder.FallbackConvert(System.Dynamic.DynamicMetaObject) Unknown
System.Dynamic.Runtime.dll!System.Dynamic.DynamicMetaObject.BindConvert(System.Dynamic.ConvertBinder) Unknown
System.Dynamic.Runtime.dll!System.Dynamic.ConvertBinder.Bind(System.Dynamic.DynamicMetaObject, System.Dynamic.DynamicMetaObject[]) Unknown
System.Dynamic.Runtime.dll!System.Dynamic.DynamicMetaObjectBinder.Bind(object[], System.Collections.ObjectModel.ReadOnlyCollection<System.Linq.Expressions.ParameterExpression>, System.Linq.Expressions.LabelTarget) Unknown
System.Dynamic.Runtime.dll!System.Runtime.CompilerServices.CallSiteBinder.BindCore<System.Func<System.Runtime.CompilerServices.CallSite, object, object>>(System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, object, object>>, object[]) Unknown
System.Dynamic.Runtime.dll!System.Runtime.CompilerServices.CallSiteOps.Bind<System.Func<System.Runtime.CompilerServices.CallSite, object, object>>(System.Runtime.CompilerServices.CallSiteBinder, System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, object, object>>, object[]) Unknown
[Native to Managed Transition]
[Managed to Native Transition]
System.Linq.Expressions.dll!System.Linq.Expressions.Interpreter.MethodInfoCallInstruction.InvokeWorker(object[]) Unknown
System.Linq.Expressions.dll!System.Linq.Expressions.Interpreter.MethodInfoCallInstruction.Invoke(object[]) Unknown
System.Linq.Expressions.dll!System.Linq.Expressions.Interpreter.MethodInfoCallInstruction.Run(System.Linq.Expressions.Interpreter.InterpretedFrame) Unknown
System.Linq.Expressions.dll!System.Linq.Expressions.Interpreter.Interpreter.Run(System.Linq.Expressions.Interpreter.InterpretedFrame) Unknown
System.Linq.Expressions.dll!System.Linq.Expressions.Interpreter.LightLambda.Run(object[]) Unknown
System.Linq.Expressions.dll!System.Linq.Expressions.Interpreter.CallInstruction.InterpretLambdaInvoke(System.Linq.Expressions.Interpreter.LightLambda, object[]) Unknown
System.Linq.Expressions.dll!System.Linq.Expressions.Interpreter.MethodInfoCallInstruction.InvokeWorker(object[]) Unknown
System.Linq.Expressions.dll!System.Linq.Expressions.Interpreter.MethodInfoCallInstruction.Invoke(object[]) Unknown
System.Linq.Expressions.dll!System.Linq.Expressions.Interpreter.MethodInfoCallInstruction.Run(System.Linq.Expressions.Interpreter.InterpretedFrame) Unknown
System.Linq.Expressions.dll!System.Linq.Expressions.Interpreter.Interpreter.Run(System.Linq.Expressions.Interpreter.InterpretedFrame) Unknown
System.Linq.Expressions.dll!System.Linq.Expressions.Interpreter.LightLambda.Run(object[]) Unknown
[Lightweight Function]
ProblematicUsageOfGenericsAndDynamic.exe!ProblematicUsageOfGenericsAndDynamic.ProblemClassA.Trouble<object>(System.Linq.Expressions.Expression<System.Func<object>>, out object) C#
ProblematicUsageOfGenericsAndDynamic.exe!ProblematicUsageOfGenericsAndDynamic.ProblemClassB.Test(string, object) C#
ProblematicUsageOfGenericsAndDynamic.exe!ProblematicUsageOfGenericsAndDynamic.MainPage.MainPage() C#
ProblematicUsageOfGenericsAndDynamic.exe!ProblematicUsageOfGenericsAndDynamic.ProblematicUsageOfGenericsAndDynamic_XamlTypeInfo.XamlTypeInfoProvider.Activate_0_MainPage() C#
ProblematicUsageOfGenericsAndDynamic.exe!ProblematicUsageOfGenericsAndDynamic.ProblematicUsageOfGenericsAndDynamic_XamlTypeInfo.XamlUserType.ActivateInstance() C#
[Native to Managed Transition]
[Managed to Native Transition]
ProblematicUsageOfGenericsAndDynamic.exe!ProblematicUsageOfGenericsAndDynamic.App.OnLaunched(Windows.ApplicationModel.Activation.LaunchActivatedEventArgs) C#
我简化了代码,以便您可以自己查看和测试:
ProblemClassA.cs :
using System.Linq.Expressions;
public class ProblemClassA
{
private dynamic GetValue<T>(Expression<Func<T>> argument)
{
var getterLambda = Expression.Lambda<Func<dynamic>>(argument.Body);
var getter = getterLambda.Compile();
return getter();
}
public void Trouble<T>(Expression<Func<T>> argument, out T argumentValue)
{
argumentValue = this.GetValue(argument);
}
public void JustFine(Expression<Func<object>> argument, out object argumentValue)
{
argumentValue = this.GetValue(argument);
}
}
ProblemClassB.cs:
public class ProblemClassB
{
public void Test(string aString, object anObject)
{
ProblemClassA problemClassA = new ProblemClassA();
object valueString;
object valueObject;
problemClassA.JustFine(() => aString, out valueString); // Works fine
problemClassA.JustFine(() => anObject, out valueObject); // Works fine
problemClassA.Trouble(() => aString, out valueString); // Works fine as well
problemClassA.Trouble(() => anObject, out valueObject); // Throws an exception NullReferenceException
}
}
如何测试:
通过在Test
的实例上调用ProblemClassA
来测试它,例如:
new ProblemClassA().Test("This is a test", new object());
有人可以向我解释为什么会抛出异常吗?
提前致谢!