2010-09-07 7 views

Respuesta

22

uso de LINQ:

List<string> usernames = users.Select(u => u.UserName).ToList(); 
+0

innecesariamente un desperdicio en comparación con ConvertAll según respuesta SLaks' a menos que '' de los usuarios tiene 4 o menos elementos. –

4
var usernames = users.Select(u => u.Username).ToList(); 
12

De esta manera:

List<string> userNames = users.ConvertAll(u => u.UserName); 

Tenga en cuenta que la lista userNames no reflejará los cambios posteriores a la users o sus UserName s.

5

Si realmente necesita una lista, entonces el método LINQ es lo mejor que puede hacer (podría haber una mejora de velocidad marginal en la creación de una nueva lista con la capacidad adecuada y luego agregar, pero es poco probable que sea apreciable.

Editar:. Si usted va a hacer esto, utilice ConvertAll no Select seguido de ToList, especialmente si su lista podría ser grande ConvertAll preasigna al tamaño correcto, cuya importancia en el rendimiento crece con el tamaño de la lista de fuentes .

Si quieres un IList de sólo lectura que actúa como usted ha hecho esto, entonces se puede ge t mucho mejor rendimiento de la conversión de una clase de lista:

public class ConvertingList<TSrc, TDest> : IList<TDest> 
{ 
    private readonly IList<TSrc> _inner; 
    private readonly Func<TSrc, TDest> _conv; 
    public ConvertingList(IList<TSrc> inner, Func<TSrc, TDest> conv) 
    { 
     _inner = inner; 
     _conv = conv; 
    } 
    public TDest this[int index] 
    { 
     get 
     { 
      return ReferenceEquals(null, _inner[index]) ? default(TDest) : _conv(_inner[index]); 
     } 
     set 
     { 
     throw new NotSupportedException("Readonly collection"); 
     } 
    } 
    public int Count 
    { 
     get 
     { 
     return _inner.Count; 
     } 
    } 
    public bool IsReadOnly 
    { 
     get 
     { 
     return true; 
     } 
    } 
    public int IndexOf(TDest item) 
    { 
     if(ReferenceEquals(item, null)) 
     { 
     for(int i = 0; i != Count; ++i) 
      if(ReferenceEquals(this[i], null)) 
      return i; 
     } 
     else 
     { 
     for(int i = 0; i != Count; ++i) 
      if(item.Equals(this[i])) 
      return i; 
     } 
     return -1; 
    } 
    public void Insert(int index, TDest item) 
    { 
     throw new NotSupportedException("Readonly collection"); 
    } 
    public void RemoveAt(int index) 
    { 
     throw new NotSupportedException("Readonly collection"); 
    } 
    public void Add(TDest item) 
    { 
     throw new NotSupportedException("Readonly collection"); 
    } 
    public void Clear() 
    { 
     throw new NotSupportedException("Readonly collection"); 
    } 
    public bool Contains(TDest item) 
    { 
     return IndexOf(item) != -1; 
    } 
    public void CopyTo(TDest[] array, int arrayIndex) 
    { 
     if(array == null) 
     throw new ArgumentNullException(); 
     if(arrayIndex < 0) 
      throw new ArgumentOutOfRangeException(); 
     if(array.Rank != 1 || array.Length < arrayIndex + Count) 
      throw new ArgumentException(); 
     foreach(TDest item in this) 
      array[arrayIndex++] = item; 
    } 
    public bool Remove(TDest item) 
    { 
     throw new NotSupportedException("Readonly collection"); 
    } 
    public IEnumerator<TDest> GetEnumerator() 
    { 
     foreach(TSrc srcItem in _inner) 
     yield return ReferenceEquals(null,srcItem) ? default(TDest) : _conv(srcItem) 
    } 
    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

Con esto, entonces:

IList<string> userNames = new ConvertingList<User, string>(users, u => u.Username); 

va a crear un nuevo objeto en tiempo constante que se comporta como una lista de sólo lectura de los nombres.

(A salvaguardia contra un nulo de usuario devuelve una cadena nula aquí, otro comportamiento puede ser suministrado por supuesto).

+0

La lista de solo lectura demora la ejecución de su función de conversión. Entonces, si va a usar la lista, que probablemente tendrá, el tiempo ahorrado se necesitará más adelante. Peor aún: si desea hacer un bucle en la lista dos veces, su función de conversión se ejecuta una y otra vez, lo que resulta en una lista más lenta. Decir que no utilizar Select se llama micro optimización, las personas no van a notar esos 10 ms adicionales. Además, Select es compatible con Microsoft, por lo que cualquier optimización en las versiones de framework más recientes beneficiará directamente a su código también. – Arcturus

+0

@Arcturus, La lista de sólo lectura es mejor o peor que 'ConvertAll' dependiendo del uso, que es precisamente eso que nos dio dos opciones como mi respuesta. Si necesitaras tal vez obtener el tamaño y luego alcanzar algunos índices, sería mucho mejor. Si necesitas repetir dos veces, es peor. Si necesitas modificar, es completamente inútil. Diciendo * * qué usar '' ConvertAll' sobre Select' es el tipo de micro-optimización que se libera una vez que están en el hábito de hacerlo de esa manera, sin ningún inconveniente. –

+0

Es cierto, pero no es innovador. Por lo tanto, use lo que encuentre más útil. IEnumerable está bien en muchos casos, por lo que la ToList no tiene sentido al usar Select.Si solo usa Count y pulsa algunos índices, probablemente sea mejor recuperarlos de la lista original por cierto. Introducir una lista completamente nueva, también significa apoyarla con testcases también. – Arcturus

1

Usted

List<string> userNames = users.ConvertAll(u => u.UserName); 
Cuestiones relacionadas