2010-09-23 23 views
14

Considera:IEnumerable <string> a cadena

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

ahora por qué la prueba está vacía después de eso? No me importa el regreso de eso, realmente sé que es IEnumerable.

de cualquier manera si todo esto parece un desastre, entonces, ¿cómo puedo convertir IEnumerable<char> en una cadena?

gracias de antemano ..

Respuesta

21

Por cuanto no ejecutar la consulta. Linq es flojo. Se ejecutará cuando lo haga foreach o ToList/ToArray/ToDictionary.

y consejos para hacerlo así

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

o incluso usando

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

Más sobre esto. Select está destinado a aplicar algún tipo de transformación a cada elemento en secuencia. Esta operación también se conoce como map. Si desea producir un solo elemento a partir de la secuencia, es Aggregate, también conocido como reduce. No es flojo, fuerza la ejecución de la consulta.

+0

'Remove'? Creo que te refieres a 'Subcadena' – Timwi

+0

@Greg Linq es un marco declarativo. esto es a veces algo sorprendente para desarrolladores de mentalidad imperativa. – Andrey

+0

Esto no se compilará si 'somestring' es de tipo' IEnumberable '. La clase de cadena no tiene un constructor sobrecargado que toma una matriz de cadena. –

2

Porque Select es flojo, por lo que la función que pase solo se evaluará una vez que use el resultado de Seleccionar.

En general, es una mala idea usar funciones con efectos secundarios con Seleccionar. Probablemente deberías usar foreach en su lugar.

En este caso particular, puede simplemente usar el método String.Join.

3

Select devuelve IEnumerable<char> pero no lo está enumerando en su código por lo que el delegado no se ejecutará. Si lo cambia a:

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

Porque solo ha declarado la secuencia, pero nunca la ha ejecutado. Si agregó otro .ToList() al final, entonces test tendría los caracteres en él.

Sin embargo, lo recomiendo encarecidamente en contra de esta práctica. Está utilizando la evaluación de una secuencia a causando efectos secundarios. Ya has descubierto que los resultados son confusos. Si realmente desea que los primeros 50 elementos de una secuencia, sólo tiene que utilizar Take solo:

var partSequence = fullSequence.Take(50); 

Su ejemplo anterior se podría escribir algo como esto:

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

pero estoy seguro de que está consciente de string.Substring() para este propósito.

14

(Otros han explicado por qué no funciona.)

Su pregunta no acaba de tener sentido en el momento - no está claro si eres realidad se trata de un IEnumerable<char> o un IEnumerable<string>. (Su texto sugiere IEnumerable<string>; su código sugiere IEnumerable<char>). Si se trata de un IEnumerable<string> y está utilizando .NET 4, que es muy fácil:

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

Si está utilizando .NET 3.5, sigue siendo bastante fácil:

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

usar Obviamente algo así como " , "si quieres un delimitador entre las cadenas.

Si usted está tratando con un general IEnumerable<char> a continuación, utilizar

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

Si eres realidad se trata de una cadena para empezar, utilizar Substring :)

+1

Sí, pero creo que se está preguntando por qué su código no funcionó. – Timwi

+0

itera sobre la cadena, mira 'delegate (char x)'. No creo que sea eficiente hacer una cuerda. Únete por encima de los caracteres. – Andrey

+0

@Andrey: Estaba basando la respuesta en la afirmación de que está intentando concatenar un 'IEnumerable ', no un 'IEnumerable ' ... básicamente la pregunta está rota en este momento. He editado para indicar eso. –

Cuestiones relacionadas