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

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

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

Я бы предположил, что все может быть создано с проверкой времени компиляции или через атрибуты, без необходимости изменения среды 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 не должны иметь возможности изменять состояние самостоятельно класс или экземпляры переданных им ссылочных типов. Кроме того, функции уровня const могут вызывать только другие функции уровня const в своей области.

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

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

Итак, в чем причина того, что это не реализовано? Проблемы юзабилити (понимание константы в C++ обычно довольно сложно для новых пользователей), проблемы языкового дизайна (не может быть сделано) или просто приоритетные проблемы (дни неизменности-buzz закончились)..?

6 ответов


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

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

проблема с постоянством в том, что оно должно быть действие. Это проблема в C# , когда произвольное другое язык может использовать класс C# и полностью игнорировать const-ness только потому, что язык его не поддерживает. Закрепление его на каждом другом языке CLS только потому, что C# поддерживает его, конечно, очень непрактичный.

применимость также является проблемой в C++. Поскольку язык также поддерживает const_cast. Любой клиентский код может бросить константность прочь быстро и undiagnosably. Ты не должен, но иногда приходится. Потому что есть два вида постоянства: строгое и наблюдаемое. Примерно аналогично частной и общественной. The mutable ключевое слово было добавлено к языку позже, чтобы попытаться справиться с необходимостью наблюдаемая константа, поэтому, по крайней мере, можно избежать неизбежного использования const_cast. Некоторые говорят, что C++ - сложный язык. Не слышу этого от C#.


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


как я считаю, что это так,const означает разные вещи в C# по сравнению с C++.

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


однажды меня удивила следующая ситуация:

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);
}

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

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

и теперь, начиная с a ist ничего, кроме ссылки на вектор.Vector3 последний также имеет вектор.Vector3[0] = = 2,87!

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

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

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 никогда не будет изменена.


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

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

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

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


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

ваш первый пример может быть переписан юридически как

public class NumberContainer
{
    private readonly int number;

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

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

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