1
Vote

When calling a public method on a private class which takes a ref param and passing a StrongBox the strong box doesn't get updated

description

<Thanks>David Miller</Thanks>
 
   class Dummy
    {
        public int m1(int x) { return x; }
        public int m1(ref int x) { x = x+1; return x; }
    }
 
        Dummy dummy = new Dummy();
 
        imb = new TestInvokeMemberBinder(mydefBinder, "m1", false, cinfo);
        MSC::System.Runtime.CompilerServices.StrongBox<int> box = new MSC::System.Runtime.CompilerServices.StrongBox<int>(12);
 
        dyn = Expression.Dynamic(imb, typeof(object), Expression.Constant(dummy), Expression.Constant(box));
        lambda = Expression.Lambda(dyn);
        d = lambda.Compile();
        o = d.DynamicInvoke(null);
        Console.WriteLine("Dynamic2: {0}, box is {1}", o,box.Value);
 
the overload resolver produces this code:
 
.Block(System.Int32 $outParam) {
.Block(System.Object $$ret) {
    $$ret = .Block() {
        .If (
            $$arg1 .Is System.Runtime.CompilerServices.StrongBox`1[System.Int32]
        ) {
            $outParam = $$arg1.Value
        } .Else {
            .Call Microsoft.Scripting.Runtime.ScriptingRuntimeHelpers.IncorrectBoxType((System.Object)$$arg1)
        };
        .Call Microsoft.Scripting.Runtime.BinderOps.InvokeMethod(
            .Constant<System.Reflection.MethodInfo>(Int32 m1(Int32 ByRef)),
            (System.Object)$$arg0,
            .NewArray System.Object[] {
                (System.Object)$outParam
            })
    };
    ((System.Runtime.CompilerServices.StrongBox`1[System.Int32])$$arg1).Value = $outParam;
    $$ret
}
}
and the out param is never updated because we don't take the updated value from the object array that we create to invoke via reflection.

comments

dinov wrote Dec 3, 2009 at 9:11 PM

We also have a different return type when invoking via reflection - object for reflected calls, strongly typed for non-reflected calls. That prevents the language from performing their custom boxing when doing a reflected call.