Почему строка не реализует IList <char>? - PullRequest
4 голосов
/ 21 августа 2011

В заголовке написано все

Почему String реализует IEnumerable<char>, а не IList<char>?

Строка имеет длинуи вы уже можете брать элементы из определенного индекса.
И можно указать, что он неизменен с ICollection<char>.IsReadOnly.

Так что же может быть не так с этим?Я что-то упускаю?

На это указывают многие ответы: Не существует интерфейса только для списков / коллекций только для чтения, но, как показывает ReadOnlyCollection<T>, я думаю, что это определенновозможно и с IsReadOnly Свойство, разработанное для таких случаев.

   public class String : IList<char>
    {
        int IList<char>.IndexOf(char item)
        {
            // ...
        }

        void IList<char>.Insert(int index, char item)
        {
            throw new NotSupportedException();
        }

        void IList<char>.RemoveAt(int index)
        {
            throw new NotSupportedException();
        }

        char IList<char>.this[int index]
        {
            set
            {
                throw new NotSupportedException();
            }
        }

        void ICollection<char>.Add(char item)
        {
            throw new NotSupportedException();
        }

        void ICollection<char>.Clear()
        {
            throw new NotSupportedException();
        }

        public bool Contains(char item)
        {
            // ...
        }

        public void CopyTo(char[] array, int arrayIndex)
        {
            // ...
        }

        int ICollection<char>.Count
        {
            get { return this.Length; }
        }

        public bool IsReadOnly
        {
            get { return true; }
        }

        bool ICollection<char>.Remove(char item)
        {
            throw new NotSupportedException();
        }

        // ...
    }

Ответы [ 6 ]

14 голосов
/ 21 августа 2011

В основном потому, что IList наследуется от ICollection, а строки не поддерживают изменяемые обещания beahviors ICollection (добавление, удаление и удаление) - при добавлении или удалении символьных элементов из строки создается новыйstring.


Реализация part интерфейса - плохой дизайн.Вы можете сделать это иногда по необходимости, но это никогда не будет хорошим выбором.Лучше разделить интерфейс.(Интерфейсы коллекции .NET, вероятно, следовало бы разделить, чтобы отделить изменяемые элементы от диагностических.) Мета-функции, такие как IsReadOnly, делают интерфейс менее согласованным и затрудняют его использование.строка во многих отношениях является списком - вы можете индексировать строку и находить в ней количество символов - довольно редко кто-то действительно захочет обработать строку как IList<char>, особенно впост-3.5-мир, когда доступны простые преобразования, которые облегчают получение этой информации из IEnumerable<char>.

4 голосов
/ 21 августа 2011

То, что ReadOnlyCollection поддерживает IList, на мой взгляд, очень высоко: meh .

IList - это контракт, который указывает, что разработчики поддерживают мутацию коллекции (например, Добавить, Удалить, Вставить), которая на неизменяемом объекте явно неверна. Перенос этого на System.String является просто неправильным, поскольку он также неизменен по своему замыслу.

System.String реализация IList была бы ужасной конструкцией API, так как набор методов не работал бы, поэтому строки не работали бы так же, как типы, которые полностью реализуют IList.

Возможно, вы думаете, что он поддерживает более либеральный интерфейс, но IList - неправильный выбор.

Частичная реализация интерфейса, подобная этой, нарушает принцип подстановки Liskov и вносит потенциальные ошибки во время выполнения.

Update

Интересно, что в .Net 4.5 появился новый интерфейс IReadOnlyList . Однако String не реализует его и не может быть введен в иерархию IList.

Некоторый фон: http://www.infoq.com/news/2011/10/ReadOnly-WInRT.

2 голосов
/ 21 августа 2011

С чего бы это?Я думаю, что не так много случаев, когда это было бы полезно.Большую часть времени, когда у вас есть строка, вы знаете, что это строка.А если нет, то IEnumerable<char> часто достаточно хорош.

Более того IList<T>ICollection<T>) являются интерфейсами для изменяемых коллекций, которых string нетт.(Хотя ReadOnlyCollection<T> их реализует.)

1 голос
/ 21 августа 2011

Я не уверен, почему альтернатива, представленная ниже, еще не выдвинута ...

System.String поддерживает это (хотя и косвенно). Да, он делает еще одну копию в памяти, но я считаю, что она спроектирована таким образом, потому что строки неизменны.

string myString = "hello world";    
IList<char> myIList = myString.ToCharArray();
1 голос
/ 21 августа 2011

В основном, это не IList (вы не можете "hello world".Add('!') - это несовместимость интерфейса и контракта; это не просто список только для чтения, потому что это «знает» эту операцию Addи вызывать при вызове).


Также у строк есть особая семантика - на ум приходят оптимизация хранилища и псевдонимы идентификаторов (могут быть небольшие оптимизации строк, могут бытьинтернированные строки).Они не будут выделяться, как только вы примете IList<char> - люди могут начать ожидать «нормальной» List <> - подобной семантике.

Однако при просмотре IEnumerable<char> такие ожидания не возникают (этопросто говорит: я могу дать вам несколько символов подряд, вам не нужно знать, откуда они берутся).

0 голосов
/ 06 ноября 2013

Тот факт, что String не реализует IList<char>, меня не удивляет. На самом деле, что меня несколько удивляет, так это то, что он реализует IEnumerable<char>.

Почему? Потому что строка на самом деле не является последовательностью символов.

Видите ли, в Unicode есть 1114,112 кодовых точек, но char - это всего 16 бит. Строка содержит последовательность символов (т. Е. Кодовые точки Юникода), которые кодируются с использованием UTF16 в количестве значений char. В результате число символов Юникода в строке может быть меньше количества char значений в строке.

Теперь я понимаю, что это звучит очень странно для большинства людей, особенно для тех, кто говорит по-английски, потому что они всегда были довольны ASCII и предполагали, что один char равен одному символу. Во многих случаях это предположение даже верно. Это может быть причиной того, что string реализует IEnumerable<char>, как своего рода компромисс с устаревшим миром, не поддерживающим юникод.

Но правда в том, что мы не можем ответить на ваш вопрос. Единственные, кто может сказать вам, почему они спроектировали струны так, как они это сделали, - это люди из команды BCL в то время.

...