De hecho, su código hace algo que es fundamentalmente muy funcional, es decir, se reduce una lista de cadenas a una sola cadena mediante la concatenación de los elementos de la lista. Lo único imperativo sobre el código es el uso de un StringBuilder
.
El código funcional lo hace mucho más fácil, en realidad, porque no requiere un caso especial como lo hace su código. Mejor aún, .NET ya tiene esta operación en particular en práctica, y probablemente más eficiente que su código 1):
return String.Join(", ", ListOfResources.Select(s => s.Id.ToString()).ToArray());
(Sí, la llamada a ToArray()
es molesto pero Join
es un método muy antiguo y . es anterior LINQ)
Por supuesto, una versión “mejor” de Join
podría utilizarse como esto:
return ListOfResources.Select(s => s.Id).Join(", ");
La implementación es bastante sencilla, pero una vez más, usar el StringBuilder
(para el rendimiento) lo hace imperativo.
public static String Join<T>(this IEnumerable<T> items, String delimiter) {
if (items == null)
throw new ArgumentNullException("items");
if (delimiter == null)
throw new ArgumentNullException("delimiter");
var strings = items.Select(item => item.ToString()).ToList();
if (strings.Count == 0)
return string.Empty;
int length = strings.Sum(str => str.Length) +
delimiter.Length * (strings.Count - 1);
var result = new StringBuilder(length);
bool first = true;
foreach (string str in strings) {
if (first)
first = false;
else
result.Append(delimiter);
result.Append(str);
}
return result.ToString();
}
1) Sin haber visto la puesta en práctica en el reflector, supongo que String.Join
hace una primera pasada sobre las cuerdas para determinar la longitud total. Esto se puede utilizar para inicializar el StringBuilder
en consecuencia, ahorrándose costosas operaciones de copia más adelante.
EDITAR por SLaks: Aquí está la fuente de referencia para la parte pertinente del String.Join
de Net 3.5:
string jointString = FastAllocateString(jointLength);
fixed (char * pointerToJointString = &jointString.m_firstChar) {
UnSafeCharBuffer charBuffer = new UnSafeCharBuffer(pointerToJointString, jointLength);
// Append the first string first and then append each following string prefixed by the separator.
charBuffer.AppendString(value[startIndex]);
for (int stringToJoinIndex = startIndex + 1; stringToJoinIndex <= endIndex; stringToJoinIndex++) {
charBuffer.AppendString(separator);
charBuffer.AppendString(value[stringToJoinIndex]);
}
BCLDebug.Assert(*(pointerToJointString + charBuffer.Length) == '\0', "String must be null-terminated!");
}
no todo es un clavo ... – AwkwardCoder
@Eric: ¿Ve algo mal con el uso de un método de extensión ForEach para ejecutar código de generación de efectos no secundarios, p. haciendo un WriteLn en cada resultado de la consulta? –
@Tom: No estoy siguiendo tu línea de pensamiento aquí. Sin duda, escribir una línea es un efecto secundario, ¿no? –