2009-05-10 30 views
34

Normalmente, elegiría List<String> [o, en VB, List(Of String)] sobre StringCollection siempre que sea posible: véase también Best string container.StringCollection Convertir a la lista <String>

Sin embargo, como parece, los genéricos, y por lo tanto, List<String>, aparentemente no son compatibles con el diseñador de configuraciones de VS 2008. Por lo tanto, si quiero usar una lista de cadenas en mi configuración de usuario, tengo que recurrir a usar un StringCollection allí.

Ahora, como no quiero ver StringCollection a lo largo de mi código, necesito convertirlo a List<String>. ¿Cómo hago esto de manera eficiente? O, mejor aún, ¿me equivoco y hay una forma de usar List<String> en el diseñador de configuraciones?

EDIT: Tengo que usar .NET 2.0.

Respuesta

13

Si usted tiene utilizar .NET 2.0, que se imagina la opción cleanliest sería la creación de un contenedor para StringCollection que implementa IEnumerable<string> y IEnumerator<string> para StringCollection y StringEnumerator respectivamente. (nota: según los metadatos, StringEnumerator no implementa IEnumerator). Muestra a continuación. Sin embargo, al final del día, alguien, en algún lugar va a estar haciendo un foreach() sobre el StringCollection, por lo que uno podría argumentar que un simple foreach(string item in stringCollection) y agregar al List<string> sería suficiente; Dudo que esto no sea lo suficientemente performat para sus necesidades.

También puede implementar IList<string> usando este enfoque, para ahorrarle la duplicación de las cadenas subyacentes, pero pagará una penalización por tener las llamadas delegadas del tipo "envoltorio" (¡una llamada más al método en la pila!). Yo sugeriría que trate las cosas en términos de interfaces dentro de su sistema de todos modos IEnumberable<string>, IList<string> etc., en lugar de la Lista concreta, lo guiará por un camino hacia una mayor flexibilidad.

static void Main(string[] args) 
    { 
     StringCollection stringCollection = new StringCollection(); 
     stringCollection.AddRange(new string[] { "hello", "world" }); 

     // Wrap! 
     List<string> listOfStrings = new List<string>(new StringCollectionEnumerable(stringCollection)); 

     Debug.Assert(listOfStrings.Count == stringCollection.Count); 
     Debug.Assert(listOfStrings[0] == stringCollection[0]); 

    } 

    private class StringCollectionEnumerable : IEnumerable<string> 
    { 
     private StringCollection underlyingCollection; 

     public StringCollectionEnumerable(StringCollection underlyingCollection) 
     { 
      this.underlyingCollection = underlyingCollection; 
     } 

     public IEnumerator<string> GetEnumerator() 
     { 
      return new StringEnumeratorWrapper(underlyingCollection.GetEnumerator()); 
     } 

     System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
     { 
      return this.GetEnumerator(); 
     } 
    } 

    private class StringEnumeratorWrapper : IEnumerator<string> 
    { 
     private StringEnumerator underlyingEnumerator; 

     public StringEnumeratorWrapper(StringEnumerator underlyingEnumerator) 
     { 
      this.underlyingEnumerator = underlyingEnumerator; 
     } 

     public string Current 
     { 
      get 
      { 
       return this.underlyingEnumerator.Current; 
      } 
     } 

     public void Dispose() 
     { 
      // No-op 
     } 

     object System.Collections.IEnumerator.Current 
     { 
      get 
      { 
       return this.underlyingEnumerator.Current; 
      } 
     } 

     public bool MoveNext() 
     { 
      return this.underlyingEnumerator.MoveNext(); 
     } 

     public void Reset() 
     { 
      this.underlyingEnumerator.Reset(); 
     } 
    } 
84

La conversión de StringCollection a List<string> es maravillosamente simple si está usando .NET 3.5.

var list = stringCollection.Cast<string>().ToList(); 

En cuanto a su segunda pregunta, sí parece que recordar que es posible utilizar List<string> en el diseñador de configuración de Visual Studio. Si selecciona el tipo personalizado y luego el navegador al tipo apropiado, debería funcionar. Sin embargo, podría confundirme con eso, así que tendré que verificarlo.

+2

Si el rendimiento es una preocupación, elegiría Cast en lugar de OfType, sólo para evitar el ensayo del tipo que OfType está realizando. Sabemos que todas las instancias son de tipo cadena. De todos modos, esto puede ser insignificante. –

+0

@ Jerome: Sí, probablemente tengas razón al respecto, aunque en realidad debería ser insignificante en la mayoría de las situaciones. Llamar a OfType en lugar de Cast solo es realmente necesario cuando se trata de colecciones de tipos mixtos de todos modos. (No estoy seguro si se dio cuenta de que acababa de actualizar la respuesta poco antes de su comentario de todos modos, exactamente por este motivo.) – Noldorin

+0

No, no puede ingresar a la Lista en la Configuración: Acabo de intentarlo. "Personalizado" no está disponible en VS2008/.Net2 y "Buscar" no lo reconoce. (Sí, por el momento estoy atrapado en .NET2, 4.0 está en juego, pero no hasta el próximo año) – winwaed

2

Si estás usando C# .NET 3.0 y 3.5, se puede crear una lista con

var list = new List<string>(new StringCollection().Cast<string>()); 

El revés es:

var c = new StringCollection(); 
c.AddRange(new List<string>().ToArray()); 
5

Por qué no que sea sencillo y simplemente iterar a pesar de ello y agregar los elementos a la lista, o he entendido mal algo?

public static List<string> Convert(StringCollection collection) 
{ 
    List<string> list = new List<string>(); 
    foreach (string item in collection) 
    { 
     list.Add(item); 
    } 
    return list; 
} 
13

stringCollection.Cast<string>().ToList()

2

C# 2,0

StringCollection colString = new StringCollection(); 
string[] arrString = new string[colString.Count]; 
colString.CopyTo(arrString, 0); 
List<string> lstString = new List<string>(arrString); 
Cuestiones relacionadas