2010-09-23 18 views
14

dies berücksichtigen:IEnumerable <string> bespannen

string test = ""; 
somestring.ToList().Take(50).Select(
    delegate(char x) 
    { 
     test += x; 
     return x; 
    } 
); 

jetzt, warum ist Test danach leer? Ich interessiere mich nicht für die Rückkehr von das tatsächlich ich kenne IEnumerable.

jeder weg, wenn dies alles scheint ein Chaos dann wie kann ich konvertieren IEnumerable<char> zu string?

Dank im Voraus ..

Antwort

21

Da Sie die Abfrage nicht ausgeführt haben. Linq ist faul. Es wird ausgeführt, wenn Sie entweder foreach oder ToList/ToArray/ToDictionary tun.

und ich Rat es so, dass

string test = new string(somestring.Take(50).ToArray()); 

oder sogar mit

string test = somestring.Substring(0, 50); 

Mehr über das zu tun. Select soll eine Art von Transformation auf jedes Element in der Reihenfolge anwenden. Dieser Vorgang wird auch als map bezeichnet. Wenn Sie ein einzelnes Element aus der Sequenz erzeugen wollen, ist es Aggregate, aka reduce. Es ist nicht faul, es zwingt die Ausführung der Abfrage.

+0

'Remove'? Ich denke, du meinst "Substring"? – Timwi

+0

@Greg Linq ist ein deklaratives Framework. das ist manchmal überraschendes Zeug für imperativ orientierte Entwickler. – Andrey

+0

Dies wird nicht kompiliert, wenn 'somestring' vom Typ' IEnumberable 'ist. Die Zeichenfolgenklasse hat keinen überladenen Konstruktor, der ein Zeichenfolgenarray verwendet. –

2

Da Select faul ist, wird die übergebene Funktion nur ausgewertet, wenn Sie das Ergebnis von Select verwenden.

Im Allgemeinen ist es eine schlechte Idee, Funktionen mit Nebenwirkungen mit Select zu verwenden. Sie sollten wahrscheinlich stattdessen foreach verwenden.

In diesem speziellen Fall können Sie einfach die String.Join-Methode verwenden.

3

Select gibt eine IEnumerable<char> zurück, aber Sie sind nicht in Ihrem Code aufzuführen, damit der Delegat nicht ausgeführt wird. Wenn Sie es ändern in:

3

Weil Sie nur die Sequenz deklariert, aber Sie haben es nie ausgeführt. Wenn Sie am Ende ein weiteres .ToList() hinzugefügt haben, dann hätte test die Zeichen darin.

Allerdings empfehle ich dringend gegen diese Praxis. Sie verwenden die Auswertung einer Sequenz zu verursachen Nebenwirkungen. Sie haben bereits festgestellt, dass die Ergebnisse verwirrend sind. Wenn Sie wirklich nur die ersten 50 Elemente einer Sequenz möchten, verwenden Sie nur Take allein:

var partSequence = fullSequence.Take(50); 

Ihr obige Beispiel etwas wie folgt geschrieben werden:

var partString = new string(someString.Take(50).ToArray()); 

aber ich bin sicher, du bist bewusst von string.Substring() für diesen Zweck.

14

(Andere haben erklärt, warum es nicht funktioniert.

)

Ihre Frage nicht ganz Sinn im Moment machen - es ist nicht klar, ob Sie sind tatsächlich mit einem IEnumerable<char> oder einem IEnumerable<string> handeln. (Ihr Text schlägt IEnumerable<string> vor; Ihr Code schlägt IEnumerable<char> vor). Wenn es eine IEnumerable<string> ist und Sie verwenden .NET 4, dann ist es ganz einfach:

string combined = string.Join("", list.Take(50)); 

Wenn Sie .NET 3.5 verwenden, es ist immer noch recht einfach:

string combined = string.Join("", list.Take(50).ToArray()); 

Offensichtlich etwas wie " , "wenn Sie ein Trennzeichen zwischen den Zeichenfolgen möchten."

Wenn Sie sich mit einem allgemeinen IEnumerable<char> tun dann

string combined = new string(chars.Take(50).ToArray()); 

verwenden Wenn Sie sind eigentlich mit einem String den Umgang mit zu beginnen, verwenden Substring :)

+1

Ja, aber ich denke, er fragt sich, warum sein Code nicht funktioniert hat. – Timwi

+0

Er iteriert über den String, siehe 'delegate (char x)'. Ich denke nicht, dass es effizient ist, string.Join über viele Chars zu tun. – Andrey

+0

@Andrey: Ich habe die Antwort auf die Behauptung gestützt, dass er versucht, eine "IEnumerable ", nicht eine "IEnumerable " zu verketten ... im Grunde ist die Frage im Moment gebrochen. Ich habe das bearbeitet, um das anzuzeigen. –

Verwandte Themen