Будут ли преимущества структуры String в .Net? - PullRequest
4 голосов
/ 04 ноября 2010

Примечание: это гипотетическое обсуждение. На самом деле я не хочу реализовывать структуру String.

Класс .Net String может быть типом значения (структурой), потому что он неизменен и имеет мало членов. Но String не является типом значения. Возможно, потому что String был разработан до того, как были введены обнуляемые типы, или, возможно, чтобы соответствовать поведению строк Java.

Было бы полезно изменить String на тип значения или реализовать вариант типа String типа value? Это устранит уровень косвенности и совпадет с общим ненулевым случаем.

Ответы [ 4 ]

7 голосов
/ 04 ноября 2010

Короткий ответ

Строка имеет , чтобы иметь элемент ссылочного типа (например, char[]), чтобы иметь переменный размер. Таким образом, любой тип struct String действительно будет просто ссылочным типом, замаскированным под тип значения в любом случае.


Средний ответ

Я обсуждал это более подробно здесь . Но основной смысл моей идеи был: да, вы могли бы иметь строку «тип значения», предположительно что-то вроде этого:

public struct String
{
    char[] m_characters;

    public String(IEnumerable<char> characters)
    {
        m_characters = characters.ToArray();
    }

    public char this[int index]
    {
        get { return m_characters[index]; }
    }

    // All those other string functions... IndexOf, Substring, etc.
}

... но в действительности нет никакого смысла. Вышесказанное - это просто ссылочный тип (обертка вокруг char[]), расположенный внутри оболочки, которая обманчиво выглядит как тип значения. Более того, когда вы разрабатываете тип таким способом, вы получаете недостатки использования типа значения (например, возможности для упаковки) без каких-либо преимуществ (экземпляр вышеупомянутого типа String имеет те же требования к выделению памяти, что и эталонный наберите его обертки, поэтому он также ничего не покупает с точки зрения GC).

3 голосов
/ 04 ноября 2010

Нет. Типы значений в .Net должны иметь размер, известный во время компиляции. Размер string часто определяется только во время выполнения и, следовательно, не может быть смоделирован как тип значения.

Кроме того, тип в .Net, который является типом Value, может иметь только 1 размер. Или, проще говоря, не может быть разных экземпляров одного и того же типа значения с разными размерами. Это означает, что вам нужно представлять строки разной длины как разные типы. Например "dog" и "zebra" будут разными несовместимыми типами

Примечание

Кажется, этот вопрос можно интерпретировать двумя способами

  1. Сделать string типом значения без альтернативного хранилища
  2. Сделать string типом значения и разрешить альтернативное хранение в массиве

Мой ответ для сценария № 1. Кажется, что сценарий № 2 не имеет большого значения, поскольку он просто заменяет ссылочный тип на тип значения со встроенным ссылочным типом.

2 голосов
/ 04 ноября 2010

Это действительно будет действительная реализация.

Очень наивно это может выглядеть так:

struct String {
    readonly char[] _buffer;
    // Methods etc. …
}

Существует одна особенность по сравнению с классом string (не считая того, что она не может быть null): строка нулевого размера не заканчивается нулем! Насколько я помню, строки .NET заканчиваются нулем, чтобы облегчить взаимодействие с устаревшими API C (WinAPI).

Есть один момент, когда строковый класс имеет преимущество: интернирование может быть реализовано проще: String.Intern - это своего рода функция компоновщика, которая при одинаковом значении строки всегда возвращает один и тот же экземпляр string. Таким образом, сравнение двух интернированных строк a и b может быть значительно ускорено: теперь достаточно проверить их адреса.

Но, конечно, подобный вид интернирования строк может быть реализован для строковых структур, сравнивая, использует ли их символьный буфер один и тот же адрес.

0 голосов
/ 04 ноября 2010

Нет. Структуры любого данного типа всегда имеют одинаковую длину. Различные экземпляры строки не имеют.

...