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;
}