2012-05-23 68 views
1

我想看看我是否可以用javascript-fashion的方式編寫一些c#代碼,但我得到了意想不到的行爲。我知道C#沒有壞,但我不明白什麼是錯的,爲什麼它沒有做我認爲應該做的事。我無法從閉包修改變量,爲什麼?

代碼

class Program 
{ 
    static void Main(string[] args) 
    { 
     var person = CreatePerson(new{ 
      FirstName = "Lucas", 
      LastName = "Ontivero", 
      Age = 34 
     }); 

     Console.WriteLine("Name....... : {0}", person.FullName); 
     Console.WriteLine("IsJuvenile. : {0}", person.IsJuvenile); 

     person.SetFirstName("Pablo"); 
     Console.WriteLine("Name....... : {0}", person.FullName); 

     Console.ReadKey(); 
    } 

    static private dynamic CreatePerson(dynamic cfg) 
    { 
     string firstName = cfg.FirstName; 
     string lastName = cfg.LastName; 
     var age = cfg.Age; 

     return new{ 
      FullName = string.Format("{0} {1}", firstName, lastName), 
      FirstName = firstName, 
      LastName = lastName, 
      SetFirstName = new Action<string>(fn => firstName= fn), 
      SetLastName = new Action<string>(ln => lastName = ln), 
      IsJuvenile = age < 18 
     }; 
    } 
} 

輸出

Name....... : Lucas Ontivero 
IsJuvenile. : False 
Name....... : Lucas Ontivero 

但我預計

Name....... : Lucas Ontivero 
IsJuvenile. : False 
Name....... : Pablo Ontivero 

爲什麼沒有按的firstName不會改變嗎?

+0

任何方式來獲得Person類的代碼? – EtherDragon

+0

@EtherDragon:沒有類,'CreatePerson'返回一個匿名類型的實例。 –

+0

我認爲這裏的關鍵是你要返回一個匿名類型,並且匿名類型總是不可變的。你所做的任何事情(可能有反射攻擊例外)都會修改你在新建時匿名類型實例的值。 –

回答

3

它確實......但是FullName沒有。它在CreatePerson內部計算並存儲爲string,而不是稍後評估爲字符串的屬性。

您可以使用lambdas導致延遲評估,就像您使用SetFirstName一樣。

+1

另外,通過設置'firstName',他是設置局部變量'firstName'而不是字段'FirstName'? – SirPentor

+0

@SirPentor:他正在設置捕獲的變量'firstName'(在閉包中使用的變量不是本地的)。並且字段'FirstName'是對象初始化時'firstName'的副本。 –

+0

這很明顯!是一個愚蠢的問題;( – lontivero

0

它給你全名的拳頭任務。
您需要重新分配全名

FullName = string.Format("{0} {1}", firstName, lastName) 

SetFirstName功能

相關問題