2010-02-24 29 views
24

Tôi muốn để có thể viết phương pháp khuyến nông vì vậy mà tôi có thể nói:Làm cách nào để có phương pháp mở rộng thay đổi đối tượng gốc?

lines.ForceSpaceGroupsToBeTabs(); 

thay vì:

lines = lines.ForceSpaceGroupsToBeTabs(); 

Tuy nhiên, đoạn mã sau hiện kết quả đầu ra:

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

thay vì:

Tone 
TTtwo 

gì làm tôi phải thay đổi trong các mã sau đây để làm cho nó ra:

Tone 
TTtwo 

(lưu ý rằng đối tầm nhìn, . = 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; 
     } 
    } 
} 

Trả lời

36

Bạn cần phải sửa đổi các nội dung của số List<string> được chuyển đến phương pháp mở rộng, không phải biến có chứa tham chiếu đến danh sách:

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

Thật vậy. Bạn không thể chuyển đối tượng được tham chiếu "mở rộng", nhưng bạn có thể thay đổi nội dung của một người –

15

Bạn sẽ phải thay đổi nội dung của danh sách gốc - chỉ gán lại thông số để có giá trị khác sẽ không thực hiện. Một cái gì đó như thế này:

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"); 
    } 
} 

Nó đáng chú ý rằng đây có gì để làm với phương pháp khuyến nông. Hãy tưởng tượng bạn vừa gọi:

Helpers.ForceSpaceGroupsToBeTabs(lines); 

... bởi vì đó là những gì mã được dịch một cách hiệu quả. Không có gì đặc biệt về thực tế rằng nó là một phương pháp mở rộng; nếu bạn thay đổi mã để phương thức tĩnh "bình thường" sẽ hoạt động, thì nó cũng sẽ hoạt động như một phương thức mở rộng. Như đã lưu ý trong các nhận xét, một điều bạn không thể thực hiện với phương thức tiện ích là đặt tham số đầu tiên thành thông số ref.

(EDIT:.. Tôi nhận ra đây là mã giống như DTB đăng, mặc dù chúng tôi đến đó một cách độc lập Tôi giữ câu trả lời này dù sao, như nó có nhiều hơn code)

+1

không phải mã chính xác, bạn có nhóm không gian ("T"), bạn có nghĩ đến điều gì đó khác hay chỉ là lỗi đánh máy 't biên dịch) –

+0

@Jon: Sự khác biệt là, với Người trợ giúp.ForceSpaceGroupsToBeTabs anh ta có thể thay đổi tham số thành tham số "ref", trong trường hợp mã hiện tại của anh * sẽ * có hiệu ứng mong muốn. Tuy nhiên, với các phương thức mở rộng, bạn không thể tạo tham số ref ... – BFree

+0

@BFree: Đúng vậy - sẽ chỉnh sửa. –

10

Nếu đó là một loại tài liệu tham khảo , bạn phải thay đổi nội dung của nó. Nếu đó là một loại giá trị bạn đang đi vào, bạn sẽ không may mắn. Sự tồn tại của các phương thức mở rộng được đưa vào để hỗ trợ các mô hình chức năng trong C# và các mô hình chức năng, bởi bản chất của chúng, có xu hướng hướng tới bất biến của các loại, do đó không có khả năng thay đổi giá trị mà phương thức mở rộng được gọi.

Nói cách khác, trong khi bạn có thể làm điều đó, nó có thể không phù hợp với "tinh thần" của lập trình hàm.

+3

Tôi nghĩ phần thứ hai của câu trả lời này là gây hiểu nhầm. Trường hợp sử dụng áp đảo cho các phương thức mở rộng là trên các giao diện, là các kiểu tham chiếu, và trong những trường hợp đó không có giới hạn đặc biệt về đột biến: các khả năng giống hệt với các phương thức thông thường, trong đó 'a.SomeMethod(); 'tham khảo một cái gì đó khác, nhưng có thể thay đổi đối tượng mà nó đề cập đến. –

Các vấn đề liên quan