Инициализация массива C # - PullRequest
5 голосов
/ 25 апреля 2011

Как человек с опытом работы в C, C ++ и ассемблере, меня всегда беспокоила одна вещь в C #: я не могу сделать что-то вроде этого:

struct OperatorType
{
    string Operator;
    TokenType Type;
}

protected static OperatorType[] Operators = {
    { "{", TokenType.OpenBrace }
};

Я хотел бы объявить этотак что он не требует выделения и инициализации во время выполнения, но C # не позволяет этого.

Да, я понимаю, что могу инициализировать с new OperatoryType() { Operator = "{", Type = TokenType.OpenBrace }.Но не влечет ли это выделение во время выполнения и инициализацию памяти?Я знаю, что это не так уж и много, но я не понимаю, зачем это нужно здесь.

Может кто-нибудь объяснить, почему этот бит дополнительных затрат требуется в C #, или, возможно, способ сделать это без запуска?распределение времени?

Ответы [ 5 ]

9 голосов
/ 25 апреля 2011

Распределения, будь то в C # или C ++, всегда требуют выделения во время выполнения.Это скорее вопрос , когда происходит выделение.

Если вы выделите в статическом конструкторе в C #, вы выделите некоторое время перед первым использованием типа.Это должно быть безопасно и не иметь никаких дополнительных затрат по сравнению с вашей версией C ++.

Кроме того, одна вещь, которую нужно понять - распределение времени выполнения в C #, как правило, намного дешевле, чем в C ++.Это одно огромное преимущество сборщика мусора.Скорее всего, это классический случай преждевременной оптимизации.Я бы порекомендовал не беспокоиться об этом, если вы не обнаружили реальную проблему с измеренной производительностью.

5 голосов
/ 25 апреля 2011

Проблема с тем, что статические данные просто отображаются из двоичного файла, состоит в том, что для них требуется форматирование всех данных, которые должны быть заморожены во время компиляции.Поскольку среда выполнения определяет расположение структур (включая строки и массивы), компилятор не может знать, каким будет это расположение.Даже если компилятор выдает макет текущей среды выполнения, он может быть нарушен в будущем.Это означает, что только структуры с явным макетом, которые были определены в этой сборке, могут быть статически сопоставлены из файла, что, откровенно говоря, не слишком полезно.

Спецификация языка C # 4.0, раздел 7.6.10.4, говорит:

За исключением небезопасного контекста (§18.1), расположение массивов не определено.

В 18.5.8:

Порядок вкакие элементы упакованы в структуру, не указано.

Структура string фактически изменилась между .NET 3.5 и 4.0 (они удалили поле);он изменился с

[NonSerialized]
private int m_arrayLength;
[NonSerialized]
private char m_firstChar;
[NonSerialized]
private int m_stringLength;

на

[NonSerialized, ForceTokenStabilization]
private char m_firstChar;
[NonSerialized]
private int m_stringLength;

Это не проблема в C или C ++, потому что компилятор определяет расположение структур.Конечно, это также означает, что вам нужно перекомпилировать все, что использует структуру / класс, чтобы изменить его макет.

2 голосов
/ 25 апреля 2011

Вы можете использовать конструктор не по умолчанию, чтобы получить немного более эффективную версию, чем при использовании синтаксиса инициализатора объекта. На самом деле не существует выделения времени выполнения, кроме фактического массива Operators, конструктор будет вызываться для каждого местоположения в этом массиве

enum TokenType { OpenBrace, T2 };

struct OperatorType
{
    string Operator;
    TokenType Type;

    public OperatorType(string op, TokenType type)
    {
        Operator = op;
        Type = type;
    }
}

static OperatorType[] Operators = {
    new OperatorType( "{", TokenType.OpenBrace )
};
0 голосов
/ 25 апреля 2011

Если вы не хотите, чтобы он инициализировался во время выполнения, создайте его в статическом конструкторе. Так что он не будет создан, пока вы не вызовете class.Operators в первый раз.

0 голосов
/ 25 апреля 2011

Простой ответ на ваш вопрос: по замыслу. И я считаю, что синтаксис в вашем вопросе теоретически возможно реализовать. Но поскольку Эрик Липперт часто отвечает на такие вопросы, как «почему я не могу ... в C #»:

потому что никто никогда не проектировал, уточнено, внедрено, проверено, задокументировал и отправил эту функцию. Все шесть из этих вещей необходимы чтобы сделать особенность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...