2010-02-24 91 views
24

我希望能寫擴展方法這樣我就可以說:如何獲得擴展方法來更改原始對象?

lines.ForceSpaceGroupsToBeTabs(); 

代替:

lines = lines.ForceSpaceGroupsToBeTabs(); 

但是,下面的代碼目前輸出:

....one 
........two 

而不是:

Tone 
TTtwo 

什麼我有下面的代碼修改,使其輸出:

Tone 
TTtwo 

(請注意,知名度,. = space, T = \t):

using System; 
using System.Collections.Generic; 

namespace TestExtended82343 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<string> lines = new List<string>(); 
      lines.Add("....one"); 
      lines.Add("........two"); 

      lines.ForceSpaceGroupsToBeTabs(); 

      lines.ForEach(l => Console.WriteLine(l)); 
      Console.ReadLine(); 
     } 
    } 

    public static class Helpers 
    { 
     public static void ForceSpaceGroupsToBeTabs(this List<string> originalLines) 
     { 
      string spaceGroup = new String('.', 4); 
      List<string> lines = new List<string>(); 
      foreach (var originalLine in originalLines) 
      { 
       lines.Add(originalLine.Replace(spaceGroup, "T")); 
      } 
      originalLines = lines; 
     } 
    } 
} 

回答

36

你必須修改內容的List<string>傳遞給擴展方法,而不是保存對列表引用的變量:

public static void ForceSpaceGroupsToBeTabs(this List<string> lines) 
{ 
    string spaceGroup = new String('.', 4); 
    for (int i = 0; i < lines.Count; i++) 
    { 
     lines[i] = lines[i].Replace(spaceGroup, "T"); 
    } 
} 
+0

確實。你不能切換「擴展的」被引用的對象,但你可以改變其內容 – 2010-02-24 16:45:46

15

您必須更改原始列表的內容 - 只需重新分配參數以使不同的值不會執行此操作。事情是這樣的:

public static void ForceSpaceGroupsToBeTabs(this List<string> lines) 
{ 
    string spaceGroup = new String('.', 4); 
    for (int i = 0; i < lines.Count; i++) 
    { 
     lines[i] = lines[i].Replace(spaceGroup, "T"); 
    } 
} 

值得一提的是這有無關擴展方法。想象一下,你剛剛叫:

Helpers.ForceSpaceGroupsToBeTabs(lines); 

...因爲這是代碼有效轉化爲。這是一種擴展方法,沒有什麼特別之處。如果您更改代碼以便「正常」靜態方法可以工作,那麼它也將作爲擴展方法工作。正如在評論中指出的那樣,不能用做的一個擴展方法是使第一個參數爲ref參數。

(編輯:。我知道這是DTB發佈完全相同的代碼,但我們到達那裏獨立我保持這個答案,無論如何,因爲它得到了比代碼更)

+1

它不是完全相同的代碼,你有空間組(「T」),當你想到別的東西或只是一個錯字(它doesn 't編譯) – 2010-02-24 14:48:49

+0

@Jon:與Helpers不同的是。ForceSpaceGroupsToBeTabs他可以將參數更改爲「ref」參數,在這種情況下,他現有的代碼*會*具有所需的效果。儘管有擴展方法,但你不能使參數參考... – BFree 2010-02-24 14:53:25

+0

@BFree:這是真的 - 將編輯。 – 2010-02-24 15:12:05

10

如果是引用類型,你必須改變它的內容。如果它是你傳入的值類型,那麼你的運氣不好。爲了支持C#中的功能範式,擴展方法的存在已經存在,而這些功能範式,從其本質來看,傾向於類型的不變性,因此無法改變被稱爲擴展方法的值。

換句話說,雖然你可能這樣做,它可能不符合功能編程的「精神」。

+3

我認爲這個答案的第二部分是誤導性的。擴展方法的壓倒性用例在接口上,它們是引用類型,在這種情況下,對突變沒有特別限制:這些能力與普通方法相同,因爲'a.SomeMethod();'不能使'a '指的是別的東西,但可以改變它所指的對象。 – 2010-02-24 14:52:52

相關問題