2012-12-21 219 views
2

我想在另一個Action中設置一個Action,但是我傳遞給它的Action最後仍然爲null。這裏有一個簡單化例如:傳遞一個行爲作爲參考

Action<Action<VerifylocalResult>> docollectprint = (vl) => 
{ 
    vl = (vlocres) => 
        { 
         //DoStuff 
        }; 

    //This returns false, indicating the action has been set: 
    Console.WriteLine((vl == null).ToString()); 
}; 

//Hookups 
docollectprint(vlocobj.Action_NotExists); 

//This returns true, so the action has not been set: 
Console.WriteLine((vlocobj.Action_NotExists==null).ToString()); 

我已經嘗試過通過一個getter方法,而不是真正的交易,但結果是一樣的..它仍然是空進行到底。

Action<Func<Action<VerifylocalResult>>> docollectprint = (vl) => 
     { 
      Action<VerifylocalResult> theaction = vl(); 
      theaction = (vlocres) => 
       { 
        //DoStuff 
       }; 

      //This returns false, indicating the action has been set 
      Console.WriteLine((theaction == null).ToString()); 
    }; 

//Hookups 
docollectprint(() => { return vlocobj.Action_NotExists; }); 

    //This returns true, so the action has not been set 
Console.WriteLine((vlocobj.Action_NotExists==null).ToString()); 

有沒有辦法做到這一點?另外,對不起,如果這之前已經問過,但是當我搜索我發現的是人們試圖做Action<ref string x>或類似的東西。

更新(解決方案):

Func<string, Action<VerifylocalResult>> docollectprint = (msg) => 
      { 
     Action<VerifylocalResult> vl = (vlocres) => 
     { 
      /*DoStuff*/ 
     }; 
        return vl; 
      }; 

    //Hookups 
    vlocobj.Action_NotExists = docollectprint("x"); 

回答

5

引用由值默認爲通過。這意味着對引用的任何更改僅在本地進行。你應該返回一些東西,而不是試圖改變傳入的參考。來自MSDN:

  • 直到 引用它的代理超出範圍,捕獲的變量纔會被垃圾收集。
  • 在lambda表達式中引入的變量在 外部方法中不可見。

  • lambda表達式不能直接捕獲來自封閉方法的參數ref [ByRef in VB]或參數out。

  • lambda表達式中的返回語句不會導致 封閉方法返回。

  • lambda表達式不能包含goto語句,break語句, 或繼續其目標是在體外或體內 一個包含匿名函數的聲明。

+1

我明白了,謝謝!我將Action更改爲Func並讓它返回Action 。這應該工作..儘管......太快,但不能接受你的答案^^並感謝您的額外信息。 – natli

1

看來你想要一個Func<Action<VerifyLocalResult>>

Func<Action<VerifylocalResult>> docollectprint = (vl) => 
{ 
    vl = (vlocres) => 
    { 
     //DoStuff 
    }; 
    return vl; 
}; 

那麼你可以做

vlocobj.Action_NotExists = docollectprint(); 
+0

是的,在Jeff's anwer後不久就想出來了......雖然如此,謝謝; D順便說一下,你的答案中的'vl'必須被刪除才能工作,因爲Func不會接受任何參數。 – natli

2

解決你的問題,你可以使用另一個代表。首先,聲明它:

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

然後將您的方法更改爲此。

RefAction<Action<string>> docollectprint = (ref Action<string> vl) => 
{ 
    vl = vlocres => 
    { 
     //DoStuff 
    }; 
    //Action has been set 
    Console.WriteLine((vl == null).ToString()); 
}; 

Action<string> action = null; 
docollectprint(ref action); 
//Action is still set 
Console.WriteLine((action == null).ToString()); 

這當然,如果你不想使用Func出於任何原因。

+0

我試過了,它工作得很好。可能在某個時候派上用場,謝謝; D – natli

3

讓我們擺脫所有的行爲,並嘗試與一個更平凡的對象相同的例子。您的代碼是與基本上等同:

Action<string> changeString = (s) => 
    { 
     s = "result"; 
     Console.WriteLine(s); 
    }; 

串的myString = 「someString」 changeString(myString的); //引用通過值傳遞並且不起作用 changeString(「someString」); //這個應該怎麼做?

但是,你可以只返回改變的事情,或者在這種情況下,剛剛返回的東西,因爲你是不是做與它的通過任何有價值的東西,沿着線:

Func<string> getString =() => return "result"; 

string myString = "someString"; 

myString = getString(); //works 

或您的情況:

Func<Action<VerifylocalResult>> docollectprint =() => 
    { 
     return (vlocres) => 
     { 
      //DoStuff 
     }; 
    }; 

vlocobj.Action_NotExists = docollectprint(); 
+0

就像我說過的那樣是一個愚蠢的例子,所以不要太多地閱讀實際的代碼,它是不相關的。 Func <>的東西是正確的,但有人揍你; D – natli

+0

是的,但它是一個有趣的答案寫,所以我會留在:) – SWeko