Преобразовать коллекцию StringCollection в список <String> - PullRequest
39 голосов
/ 10 мая 2009

Обычно я бы выбрал List<String> [или, в VB, List(Of String)] вместо StringCollection, когда это возможно: см. Также Лучший контейнер для строк .

Однако, похоже, что дженерики - и, следовательно, List<String> - явно не поддерживаются в конструкторе настроек VS 2008. Поэтому, если я хочу использовать список строк в моих пользовательских настройках, я должен прибегнуть к использованию StringCollection там.

Теперь, когда я не хочу видеть StringCollection в моем коде, мне нужно преобразовать его в List<String>. Как мне сделать это эффективно? Или, что еще лучше, я ошибаюсь и есть способ использовать List<String> в конструкторе настроек?

РЕДАКТИРОВАТЬ: я должен использовать .NET 2.0.

Ответы [ 6 ]

98 голосов
/ 10 мая 2009

Преобразование StringCollection в List<string> удивительно просто, если вы используете .NET 3.5.

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

Что касается вашего второго вопроса, я, кажется, вспоминаю, что возможно использовать List<string> в конструкторе настроек Visual Studio. Если вы выбираете пользовательский тип, то браузер подходит к типу, он должен работать. Однако я могу ошибиться, поэтому мне нужно проверить это.

16 голосов
/ 15 апреля 2010

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

15 голосов
/ 10 мая 2009

Если у вас есть для использования .NET 2.0, я бы предположил, что самым чистым вариантом будет создание оболочки для StringCollection, которая реализует IEnumerable<string> и IEnumerator<string> для StringCollection и StringEnumerator соответственно. ( примечание : согласно метаданным, StringEnumerator не реализует IEnumerator). Образец ниже. Однако, в конце концов, кто-то где-то будет делать foreach() над StringCollection, поэтому один может утверждать, что простой foreach(string item in stringCollection) и добавление к List<string> будет достаточно; Я сомневаюсь, что этого недостаточно для ваших нужд.

Вы также можете реализовать IList<string>, используя этот подход, чтобы сэкономить дублирование базовых строк, но вы заплатите штраф за вызовы делегатов типа «обертка» (еще один вызов метода в стеке!) , Я бы посоветовал вам относиться к вещам с точки зрения интерфейсов в вашей системе в любом случае IEnumberable<string>, IList<string> и т. Д., Вместо конкретного Списка, он поможет вам найти путь к большей гибкости.

    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(); 
        }
    }
5 голосов
/ 10 мая 2009

Почему бы не сделать это простым и просто повторить его и добавить элементы в список, или я что-то неправильно понял?

public static List<string> Convert(StringCollection collection)
{
    List<string> list = new List<string>();
    foreach (string item in collection)
    {
        list.Add(item);
    }
    return list;
}
3 голосов
/ 10 мая 2009

Если вы используете C # 3.0 и .NET 3.5, вы можете создать список, используя

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

И наоборот:

var c = new StringCollection();
c.AddRange(new List<string>().ToArray());
2 голосов
/ 11 февраля 2014

C # 2.0

StringCollection colString = new StringCollection();
string[] arrString = new string[colString.Count];
colString.CopyTo(arrString, 0);
List<string> lstString = new List<string>(arrString);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...