«правильная константа» в C # - PullRequest
       40

«правильная константа» в C #

77 голосов
/ 22 сентября 2008

Суть правильности const заключается в том, чтобы иметь возможность предоставлять представление экземпляра, который не может быть изменен или удален пользователем. Компилятор поддерживает это, указывая, когда вы нарушаете константность внутри константной функции или пытаетесь использовать неконстантную функцию константного объекта. Итак, не копируя подход const, есть ли методология, которую я могу использовать в C #, которая имеет те же цели?

Я знаю об неизменности, но это не относится к объектам-контейнерам, чтобы назвать только один пример.

Ответы [ 7 ]

62 голосов
/ 22 сентября 2008

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

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

Обычно я выражаю «правильность констант» в C #, определяя представление класса только для чтения:

public interface IReadOnlyCustomer
{
    String Name { get; }
    int Age { get; }
}

public class Customer : IReadOnlyCustomer
{
    private string m_name;
    private int m_age;

    public string Name
    {
        get { return m_name; }
        set { m_name = value; }
    }

    public int Age
    {
        get { return m_age; }
        set { m_age = value; }
    }
}
28 голосов
/ 22 сентября 2008

Чтобы воспользоваться преимуществами константного безумия (или чистоты в терминах функционального программирования), вам нужно спроектировать свои классы таким образом, чтобы они были неизменяемыми, как класс String в c #.

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

23 голосов
/ 23 сентября 2008

Я просто хотел отметить, что многие из контейнеров System.Collections.Generics имеют метод AsReadOnly, который вернет вам неизменную коллекцию.

4 голосов
/ 22 сентября 2008

C # не имеет такой функции. Вы можете передать аргумент по значению или по ссылке. Сама ссылка является неизменной, если вы не укажете модификатор ref . Но ссылочные данные не являются неизменными. Поэтому вы должны быть осторожны, если хотите избежать побочных эффектов.

MSDN:

Передача параметров

3 голосов
/ 25 сентября 2008

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

    public class Customer
    {
    private readonly string m_name;
    private readonly int m_age;

    public Customer(string name, int age)
    {
        m_name = name;
        m_age = age;
    }

    public string Name
    {
        get { return m_name; }
    }

    public int Age
    {
        get { return m_age; }
    }
  }

В качестве альтернативы вы также можете добавить область доступа к свойствам, то есть public get и protected set?

    public class Customer
    {
    private string m_name;
    private int m_age;

    protected Customer() 
    {}

    public Customer(string name, int age)
    {
        m_name = name;
        m_age = age;
    }

    public string Name
    {
        get { return m_name; }
        protected set { m_name = value; }
    }

    public int Age
    {
        get { return m_age; }
        protected set { m_age = value; }
    }
  }
3 голосов
/ 22 сентября 2008

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

Интерфейсы дают вам больше гибкости в определении определенного подмножества возможностей, которые вы хотите предоставить в своем классе. Хотите постоянство? Просто предоставьте интерфейс без мутирующих методов. Хотите разрешить установку одних вещей, но не других? Предоставьте интерфейс только с этими методами.

2 голосов
/ 22 сентября 2008
  • Ключевое слово const можно использовать для констант времени компиляции, таких как примитивные типы и строки
  • Ключевое слово readonly можно использовать для констант времени выполнения, таких как ссылочные типы

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

См. Также Эффективный C #: 50 конкретных способов улучшить ваш C # (Пункт 2 - Предпочитают только чтение постоянным)

...