2009-07-21 43 views

Trả lời

33

Giả sử rằng newsplit là một IEnumerable<string>, bạn muốn:

newsplit = newsplit.Select(x => "WW"); 

Các mã mà bạn đang có tương đương như sau:

foreach(string x in newsplit.ToList()) { 
    AssignmentAction(x); 
} 

... 

public static void AssignmentAction(string x) { 
    x = "WW"; 
} 

Phương pháp này sẽ không sửa đổi x vì sự các ngữ nghĩa theo giá trị của C# và tính bất biến của các chuỗi.

+0

Là một mảng chuỗi hoặc trong trường hợp của tôi một danh sách IEnumerable như tôi không nghĩ rằng nó là gì? – Jon

+0

@Jon: mảng và Danh sách tất cả hỗ trợ giao diện IEnumerable –

+1

Tôi không nghĩ rằng Select() là những gì Jon muốn, có vẻ như anh ta muốn sửa đổi chính IEnumerable. Chọn sẽ chỉ cung cấp cho anh ta những mục đã có "WW" – AgileJon

0

Đó là do biểu thức LINQ đang tạo Anonymous Types và đây là các chỉ đọc. Họ không thể được chỉ định. Ngoài ra, trong một tiêu chuẩn cho mỗi vòng lặp, bạn không thể gán cho một bộ sưu tập đang được liệt kê. Hãy thử:

foreach (var item in newsplit) 
    { 
     item = "this won't work"; 
    } 
+0

Không có loại ẩn danh nào được tạo trong biểu thức ForEach đã cho. Tham số là một đại biểu, được áp dụng cho từng phần tử trong phép lặp; và tất nhiên, sẽ không hoạt động vì lý do bạn đưa ra. –

+0

Bạn đúng, tất nhiên - không chắc tôi đang nghĩ gì! Nhưng phần thứ hai, về các bộ sưu tập không thay đổi khi được lặp lại, đáng chú ý. Cảm ơn. –

2

ForEach sẽ cho phép bạn thao tác các thành phần của IEnumerable, nhưng không thay đổi tham chiếu của phần tử.

tức, điều này sẽ thiết lập một tài sản của mỗi phần tử trong IEnumerable Foo vào chuỗi "WW":

newsplit.ToList().ForEach(x => x.Foo = "WW"); 

Tuy nhiên, bạn sẽ không thể thay đổi các giá trị bên trong IEnumerable riêng của mình.

+0

Ít nhất trong VB.Net tôi chỉ có thể gán thuộc tính của phần tử bên trong ForEach nếu ForEach nhiều dòng, LinQ ForEach sẽ không gán tham chiếu. – Brent

17

Các câu trả lời khác đã giải thích tại sao mã hiện tại của bạn không hoạt động. Dưới đây là một phương pháp mở rộng mà sẽ sửa chữa nó:

// Must be in a static non-nested class 
public static void ModifyEach<T>(this IList<T> source, 
           Func<T,T> projection) 
{ 
    for (int i = 0; i < source.Count; i++) 
    { 
     source[i] = projection(source[i]); 
    } 
} 

Sau đó sử dụng như thế này:

newsplit.ModifyEach(x => "WW"); 

Điều đó sẽ làm việc với bất kỳ thực hiện IList<T> như mảng và List<T>. Nếu bạn cần nó để làm việc với một tùy ý IEnumerable<T> sau đó bạn đã có một vấn đề, như trình tự chính nó có thể không được mutable.

Sử dụng Select() là một cách tiếp cận chức năng hơn tất nhiên, nhưng đôi khi biến đổi một bộ sưu tập hiện có giá trị thực hiện ...

+1

@Jon: Tôi nghĩ bạn có nghĩa là newsplit.ToList(). ModifyEach (x => "WW") trong khối mã thứ hai của bạn? – jason

+2

@ Jason: Gần ... nhưng nếu bạn gọi ToList() nhưng không giữ tham chiếu đến danh sách mới đó, các sửa đổi sẽ không được giữ nguyên. Đặc biệt nó sẽ * không * sửa đổi bộ sưu tập gốc. Đã chỉnh sửa câu trả lời cho mục đích sử dụng. –

+0

@Jon: Đồng ý. Cảm ơn bạn đã làm rõ. – jason

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