Convert StringCollection to List<String>
Normally, I'd choose List<String>
[or, in VB, List(Of String)
] over StringCollection
whenever possible: see also Best string container.
However, as it seems, generics — and hence, List<String>
— are apparently not supported in VS 2008's settings designer. Therefore, if I want to use a list of strings in my user settings, I have to resort to using a StringCollection
there.
Now as I don't want to see StringCollection
throughout my code, I need to convert it to List<String>
. How do I do this efficiently? Or, even better, am I mistaken and there is a way to use List<String>
in settings designer?
EDIT: I have to use .NET 2.0.
Converting StringCollection
to List<string>
is wonderfully simple if you're using .NET 3.5.
var list = stringCollection.Cast<string>().ToList();
Regarding your second question, I do seem to recollect that it is possible to use List<string>
in the settings designer of Visual Studio. If you select custom type then browser to the appropiate type, it should work. However, I could be mistaken on that, so I'll need to verify it.
stringCollection.Cast<string>().ToList()
If you have to use .NET 2.0, I would imagine the cleanliest option would be to create a wrapper for StringCollection
that implements IEnumerable<string>
and IEnumerator<string>
for StringCollection
and StringEnumerator
respectively. (note: according to metadata, StringEnumerator
does not implement IEnumerator
). Sample below. However, at the end of the day, someone, somewhere is going to be doing a foreach()
over the StringCollection
, so one could argue that a simple foreach(string item in stringCollection)
and adding to the List<string>
would suffice; I doubt this wouldn't be performat enough for your needs.
You could also implement IList<string>
using this approach as well, to save you duplicating the underlying strings, but you'll pay a penalty of having the "wrapper" type delegate calls (one more method call on the stack!). I would suggest you treat things in-terms of interfaces within your system anyway IEnumberable<string>
, IList<string>
etc, instead of the concrete List, it will guide you down a path to greater flexibility.
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();
}
}
Why not keep it simple and just iterate though it and add the items to the list, or have i misunderstood something?
public static List<string> Convert(StringCollection collection)
{
List<string> list = new List<string>();
foreach (string item in collection)
{
list.Add(item);
}
return list;
}