2017-01-01 49 views
3

我們有1個事件,2個訂戶。當事件發生時第一個子函數(函數)改變參數,這個參數是參考類型。第二位訂戶是否會更改參數或原始參數?可以委託代理鏈中的更改參數嗎? (C#)

+1

你可以添加一個代碼示例來顯示你的意思嗎?我懷疑你所說的答案是他們得到了改變的參數,但代碼示例會使問題更清楚。 –

+1

請注意,這裏沒有任何特定的事件 - 最好是僅以代表的方式說出您的問題,並儘可能簡化。 –

回答

10

您不能將該參數更改爲具有不同的值(假設它是按值參數),但是(一如既往)您可能能夠修改該值所引用的對象。

實施例:

using System; 
using System.Text; 

class Test 
{ 
    static void Main(string[] args) 
    { 
     Action<StringBuilder> action1 = sb => 
     { 
      Console.WriteLine(sb); 
      sb = new StringBuilder("x"); 
     }; 
     Action<StringBuilder> action2 = sb => 
     { 
      Console.WriteLine(sb); 
      sb.Append("y"); 
     }; 
     Action<StringBuilder> action3 = sb => 
     { 
      Console.WriteLine(sb); 
      sb.Append("z"); 
     }; 

     Action<StringBuilder> all = action1 + action2 + action3; 
     StringBuilder builder = new StringBuilder("a"); 
     all(builder); 
     Console.WriteLine(builder); 
    } 
} 

輸出:

a 
a 
ay 
ayz 

換句話說:

  • 第一作用改變其參數的值;這並不影響別的
  • 第二個動作追加「Y」的StringBuilder對象的參數是指
  • 第三個行動可以「看到」第二行動所做的更改,並將其追加「Z」
  • 代表們已經調用
  • 後,他們的變化是顯而易見的給調用者

這一切都是完全一樣的普通方法調用按值傳遞的參數。

現在你可以聲明一個委託使用ref參數 - 此時它的行爲像一個ref參數的方法,並更改參數本身到鏈後代表可見。下面是一個使用新RefAction<T>代表一個上面的例子中的版本:

using System; 
using System.Text; 

delegate void RefAction<T>(ref T arg); 

class Test 
{ 
    static void Main(string[] args) 
    { 
     RefAction<StringBuilder> action1 = (ref StringBuilder sb) => 
     { 
      Console.WriteLine(sb); 
      sb = new StringBuilder("x"); 
     }; 
     RefAction<StringBuilder> action2 = (ref StringBuilder sb) => 
     { 
      Console.WriteLine(sb); 
      sb.Append("y"); 
     }; 
     RefAction<StringBuilder> action3 = (ref StringBuilder sb) => 
     { 
      Console.WriteLine(sb); 
      sb.Append("z"); 
     }; 

     RefAction<StringBuilder> all = action1 + action2 + action3; 
     StringBuilder builder = new StringBuilder("a"); 
     all(ref builder); 
     Console.WriteLine(builder); 
    } 
} 

現在輸出的是:

a 
x 
xy 
xyz 

...這表明在action1的變化的sb其他地方都可見。

相關問題