2009-07-21 3 views

Antwort

33

Unter der Annahme, dass newsplit ein IEnumerable<string> ist, möchten Sie:

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

Der Code, den Sie haben derzeit die folgenden entspricht:

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

... 

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

Diese Methode wird nicht x ändern wegen der Pass-by-Value-Semantik von C# und die Unveränderlichkeit von Strings.

+0

Ist ein String-Array oder in meinem Fall eine Liste IEnumerable wie ich glaube nicht, es ist? – Jon

+0

@Jon: Arrays und Liste alle unterstützen die IEnumerable Schnittstelle –

+1

Ich glaube nicht, dass ein Select() ist, was Jon will, es klingt wie er das IEnumerable selbst ändern möchte. Wählen Sie wird nur geben Sie die Elemente, die bereits "WW" sind – AgileJon

0

Dies liegt daran, dass der LINQ-Ausdruck Anonymous Types erstellt und diese schreibgeschützt sind. Sie können nicht zugeordnet werden. In einem Standard für jede Schleife können Sie auch keiner Auflistung, die aufgelistet wird, zuweisen. Versuchen Sie:

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

In dem angegebenen ForEach-Ausdruck wurde kein anonymer Typ erstellt. Der Parameter ist ein Delegat, der auf jedes Element in der Iteration angewendet wird. und natürlich, wird nicht funktionieren, aus dem Grund, den Sie geben. –

+0

Sie haben natürlich Recht - nicht sicher, was ich dachte! Aber der zweite Teil, über Sammlungen, die bei der Wiederholung unveränderlich sind, ist erwähnenswert. Vielen Dank. –

2

Die ForEach wird Ihnen erlauben, die Elemente des IEnumerable zu manipulieren, aber nicht die Referenz des Elements zu ändern.

dh dies würde gesetzt eine Foo Eigenschaft jedes Element in der IEnumerable in den String "WW":

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

Allerdings werden Sie die Werte nicht selbst innerhalb des IEnumerable ändern Lage sein.

+0

Zumindest in VB.Net konnte ich nur die Eigenschaft des Elements in ForEach zuweisen, wenn die mehrzeilige ForEach, die Linq ForEach nicht als Referenz zuweisen würde. – Brent

17

Andere Antworten haben erklärt, warum Ihr aktueller Code nicht funktioniert. Hier ist eine Erweiterung Methode, die es beheben würde:

// 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]); 
    } 
} 

Dann wie folgt verwenden:

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

, die mit jeder Implementierung von IList<T> wie Arrays und List<T> arbeiten. Wenn Sie es brauchen, um mit einer beliebigen IEnumerable<T> zu arbeiten, dann haben Sie ein Problem, da die Sequenz selbst nicht veränderbar sein kann.

Mit Select() ist ein funktioneller Ansatz natürlich, aber manchmal mutiert eine bestehende Sammlung ist Mühe wert ...

+1

@Jon: Ich denke du meintest newsplit.ToList(). ModifyEach (x => "WW") in Ihrem zweiten Codeblock? – jason

+2

@Jason: Fast ... aber wenn Sie ToList() aufrufen, aber keinen Verweis auf diese neue Liste behalten, werden die Änderungen nicht beibehalten. Insbesondere würde es die ursprüngliche Sammlung nicht modifizieren. Habe die Antwort für den beabsichtigten Zweck bearbeitet. –

+0

@ Jon: Zustimmen. Danke fürs klarstellen. – jason