2011-05-20 111 views
5

此代碼的工作在.NET4:表達式樹:調用一個方法與out或ref參數

class Program 
{ 
    static void Main(string[] args) 
    { 
     var fooExpr = Expression.Parameter(typeof(Foo), "f"); 
     var parmExpr = Expression.Parameter(typeof(int).MakeByRefType(), "i"); 
     var method = typeof(Foo).GetMethod("Method1"); 
     var invokeExpr = Expression.Call(fooExpr, method, parmExpr); 
     var delegateType = MakeDelegateType(typeof(void), new[] { typeof(Foo), typeof(int).MakeByRefType() }); 
     var lambdaExpr = Expression.Lambda(delegateType, invokeExpr, fooExpr, parmExpr); 
     dynamic func = lambdaExpr.Compile(); 
     int x = 4; 
     func(new Foo(), ref x); 
     Console.WriteLine(x); 
    } 

    private static Type MakeDelegateType(Type returnType, params Type[] parmTypes) 
    { 
     return Expression.GetDelegateType(parmTypes.Concat(new[] { returnType }).ToArray()); 
    } 
} 

class Foo 
{ 
    public void Method1(ref int x) 
    { 
     x = 8; 
    } 
} 

此代碼不(與動態調用點運行時錯誤炸燬):

class Program 
{ 
    static void Main(string[] args) 
    { 
     var fooExpr = Expression.Parameter(typeof(Foo), "f"); 
     var parmExpr = Expression.Parameter(typeof(int).MakeByRefType(), "i"); 
     var method = typeof(Foo).GetMethod("Method1"); 
     var invokeExpr = Expression.Call(fooExpr, method, parmExpr); 
     var delegateType = MakeDelegateType(typeof(void), new[] { typeof(Foo), typeof(int).MakeByRefType() }); 
     var lambdaExpr = Expression.Lambda(delegateType, invokeExpr, fooExpr, parmExpr); 
     dynamic func = lambdaExpr.Compile(); 
     int x = 4; 
     func(new Foo(), out x); 
     Console.WriteLine(x); 
    } 

    private static Type MakeDelegateType(Type returnType, params Type[] parmTypes) 
    { 
     return Expression.GetDelegateType(parmTypes.Concat(new[] { returnType }).ToArray()); 
    } 
} 

class Foo 
{ 
    public void Method1(out int x) 
    { 
     x = 8; 
    } 
} 

怎麼來的?唯一的區別是使用ref和out參數。

+2

什麼* *究竟是錯誤? – 2011-05-20 17:48:19

+0

錯誤是:「代表有一些無效參數」 ......沒有進一步的細節,沒有內部異常。出於好奇, – JoshL 2011-05-20 17:56:33

+0

,如果你在呼叫地點使用'ref'而不是'out',會發生什麼?另外,如果你用正確的'out'等簽名聲明委託類型,並嘗試使用靜態類型編譯的lambda,會發生什麼? – 2011-05-20 18:05:17

回答

-1

你有沒有試圖改變

typeof(int).MakePointerType 

代替:

typeof(int).MakeByRefType() 

在線路:

var parmExpr = Expression.Parameter(typeof(int).MakeByRefType(), "i"); 
var delegateType = MakeDelegateType(typeof(void), new[] { typeof(Foo), typeof(int).MakeByRefType() }); 

問候,

0

一個參考參數將由CLR管理一個經典變量,該變量只會是Box(封裝到一個對象中,以便通過引用傳遞元素),如果這是一個值。

允許有多個輸出,並且在編譯過程中會有更多的影響。

的表達式編譯運行,但「走出去」的有效性是在編譯時檢查。

通過有效性,我的意思是編譯器確保方法將ASSIGN值的參數。

相關問題