Подтвердить что ты не робот

Почему С# не поддерживает const на уровне класса/метода?

Мне было интересно, почему С# не поддерживает const на уровне класса или метода. Я знаю, что Джон Скит давно хотел поддерживать неизменность, и я понимаю, что использование синтаксиса функции const может помочь в этом. Добавив ключевое слово const на уровне класса, мы получим полную поддержку.

Теперь, на мой вопрос, в чем причина того, что команда С# не разработала такую ​​поддержку?

Я бы предположил, что все может быть создано с помощью проверки времени компиляции или через атрибуты без изменения CLR. Я не против того, чтобы код мог переопределить поведение const посредством отражения.

Представьте себе следующее:

const class NumberContainer
{
    public int Number { get; }
}

.. Такой класс может быть заполнен только во время построения, поэтому нам понадобится конструктор для ввода int.

Другим примером является const на уровне метода:

public int AddNumbers(NumberContainer n1, NumberContainer n2) const
{
   return n1.Number + n2.Number;
}

Методы Const-level не должны изменять состояние в своем классе или экземпляры ссылочных типов, переданные им. Кроме того, функции const-уровня могут вызывать только другие функции уровня const в области видимости.

Я не уверен, что лямбды и делегаты сделают все слишком тяжелым (или невозможным), но я уверен, что кто-то, у кого больше опыта в разработке языка и компилятора, мог бы рассказать мне.

Как отметил Стив Б в комментариях, существование readonly делает вещи немного более сложными, так как const и readonly близки к тому же во время runtime, но значения readonly не могут быть определяется во время компиляции. Я предполагаю, что мы могли бы иметь уровень const и readonly, но это может быть слишком запутанным?

Итак, в чем причина не реализации этого? Юзабилити (понимание константы на С++ обычно довольно сложно для новых пользователей), проблемы с языковым дизайном (не могут быть сделаны) или просто приоритетные проблемы (дни неуверенности переполнены)..?

4b9b3361

Ответ 1

Рискуя несколько круговым объяснением, С# не поддерживает const, потому что CLR не поддерживает его вообще. CLR не поддерживает его, потому что он абсолютно не совместим с CLS.

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

Проблема с константой заключается в том, что ее необходимо выполнить. Это проблема в С#, когда любой другой язык может использовать класс С# и полностью игнорировать константу только потому, что язык ее не поддерживает. Закрепляя его на всех других языках CLS только потому, что поддерживает С#, это, конечно, очень непрактично.

Принудительность является проблемой и в С++. Поскольку язык также поддерживает const_cast < > . Любой клиентский код может быстро и бесконтактно отбрасывать constness. Вы не должны, но иногда вам приходится. Потому что существуют две формы константы, строгие и наблюдаемые. Примерно аналогичен частной консистенции и общественной конности. Ключевое слово mutable было добавлено на язык позже, чтобы попытаться справиться с необходимостью наблюдаемой консистенции, чтобы можно было избежать, по крайней мере, неизбежного использования const_cast < > . Некоторые люди говорят, что С++ - сложный язык. Не слышите о С# много.

Ответ 2

Вы говорите, что CLR не нужно будет менять, но подумайте, что нет стандартного способа выразить эту "константу" в скомпилированных сборках, и что эти сборки не могут быть использованы кодом С# в любом случае. Это не то, что вы можете просто сделать для С# - вам нужно будет сделать это для всех языков .NET.

Ответ 3

Как я полагаю, случай, const означает разные вещи в С# по сравнению с С++.

В С# вы можете использовать ключевое слово readonly, чтобы получить уровень функциональности, который вы хотите от const.

Ответ 4

Меня когда-то превзошло следующая ситуация:

class Vector
{
    private double[] m_data;
    public int Dimension {get;set;}

    public double this[int i]
    {
        get {return m_data[i];}
        set {m_data[i] = value;}
    }

    public Vector(int n)
    {
        this.Dimension = n;
        this.m_data = new double(n);
    }

    public static Vector Zero(int n)
    {
        Vector v = new Vector(n);
        for (int i = 0; i < n; i++)
        {
            v[i] = 0.0;
        }

        return v;
     }

    public static readonly Vector Zero3 = Zero(3);
}

Thou Vector.Zero3 доступен только для чтения, и вы не можете его назначить, вы можете получить доступ к его компоненту, а затем произойдет следующая глупая вещь:

Vector a = Vector.Zero3;
a[0]     = 2.87;

и теперь, поскольку ist не является ссылкой на Vector.Vector3, последний также имеет Vector.Vector3 [0] == 2.87!

После того, как однажды я впал в эту яму, я придумал очень простой хак, хотя и не элегантный, выполняет свою функцию.

А именно, в класс, который, как я предполагаю, создает статические readontly-константы, я ввожу логический флаг:

class Vector
{
    private double[] m_data;
    public int Dimension {get;set;}
    private bool m_bIsConstant = false;
    ...

    public double this[int i]
    {
        get {return m_data[i];}
        set 
        {
           if (!m_bIsConstant)
           {
                m_data[i] = value;
           }
        }
    }
    ...
    public static Vector Zero(int n)
    {
        Vector v = new Vector(n);
        for (int i = 0; i < n; i++)
        {
            v[i] = 0.0;
        }

        v.m_bIsConstant = true;
        return v;
     }
     ...
}

Этот хак гарантирует, что ваша статическая переменная readonly никогда не будет изменена.

Ответ 5

В случае вашего предложения для const-класса вы скажете:

Такой класс может быть заполнен только во время построения, поэтому нам понадобится конструктор для ввода int

Но если все свойства доступны только для чтения, вы уже достигли того, что вы сказали.

Я не могу говорить для разработчиков языка С#, но, возможно, причина того, что const применяется к множеству других конструкций, заключается в том, что добавление просто не стоит усилий, и вы можете обойти проблему другими способами (как описано выше и в других ответах/комментариях).

Ответ 6

Я не могу сказать из вашего вопроса, как особенно важна эта перегрузка ключевого слова const.

Ваш первый пример можно переписать на законных основаниях как

public class NumberContainer
{
    private readonly int number;

    public NumberContainer(int number)
    {
        this.number = number;
    }

    public int Number
    {
        get { return number; }
    }
}

Возможно, если компилятор не сможет определить неизменность этого класса (я не знаю), может быть полезен какой-то атрибут?

В вашем втором примере я не понимаю, во что вы едете. Если функция возвращает постоянное значение, ее можно заменить на поле констант.