Смысл константной корректности состоит в том, чтобы иметь возможность предоставить представление об экземпляре, которое не может быть изменено или удалено пользователем. Компилятор поддерживает это, указывая, когда вы нарушаете константность из константной функции или пытаетесь использовать неконстантную функцию константного объекта. Итак, без копирования константного подхода, есть ли методология, которую я могу использовать в C #, которая имеет те же цели?
Я знаю о неизменности, но на самом деле это не относится к объектам контейнера, чтобы назвать лишь один пример.
c#
theory
const-correctness
tenpn
источник
источник
const_cast
на C #?Ответы:
Я тоже сталкивался с этой проблемой много раз и в конечном итоге использовал интерфейсы.
Я думаю, что важно отказаться от идеи, что 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; } } }
источник
const
без дополнительных затрат на определение отдельного интерфейса и необходимость диспетчеризации во время выполнения. То есть язык предоставляет простой способ реализации константных интерфейсов времени компиляции.const
-ness является частью дизайна и декларирует намерение так же ясно, как и написание внешнего константного интерфейса. Кроме того, предоставление константных интерфейсов может быть сложной задачей, если ее нужно решать вручную, и может потребовать написания почти такого же количества интерфейсов, сколько классов присутствует в составном типе. Это подводит нас к вашей последней фразе: «облажались из-за того, что забыли добавить константу». Легче привыкнуть добавлятьconst
везде (стоимость разработки небольшая), чем писать интерфейсы только для чтения для каждого класса.Чтобы получить преимущество константного безумия (или чистоты в терминах функционального программирования), вам нужно будет спроектировать свои классы таким образом, чтобы они были неизменными, как и класс String в C #.
Этот подход намного лучше, чем просто пометка объекта как доступного только для чтения, поскольку с помощью неизменяемых классов вы можете легко передавать данные в многозадачных средах.
источник
Builder
классов для больших неизменяемых типов (Java и .NET определяютStringBuilder
класс, который является лишь одним примером).Я просто хотел отметить, что многие контейнеры System.Collections.Generics имеют метод AsReadOnly, который вернет вам неизменяемую коллекцию.
источник
В C # такой возможности нет. Вы можете передавать аргумент по значению или по ссылке. Сама ссылка неизменна, если вы не укажете модификатор ref . Но ссылочные данные не являются неизменными. Так что нужно быть осторожным, если вы хотите избежать побочных эффектов.
MSDN:
Передача параметров
источник
Ответом на этот вопрос являются интерфейсы, которые на самом деле более эффективны, чем const в C ++. const - это универсальное решение проблемы, где «const» определяется как «не устанавливает элементы и не вызывает то, что устанавливает элементы». Это хорошее сокращение для постоянства во многих сценариях, но не во всех. Например, рассмотрим функцию, которая вычисляет значение на основе некоторых членов, но также кэширует результаты. В C ++ это считается неконстантным, хотя с точки зрения пользователя он по сути является константой.
Интерфейсы дают вам больше гибкости в определении конкретного подмножества возможностей, которые вы хотите предоставить от своего класса. Хотите постоянство? Просто предоставьте интерфейс без методов изменения. Хотите разрешить установку одних вещей, но не других? Предоставьте интерфейс только с этими методами.
источник
mutable
.Согласитесь с некоторыми другими взглядами на использование полей только для чтения, которые вы инициализируете в конструкторе, для создания неизменяемых объектов.
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 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; } } }
источник
Проблема с readonly заключается в том, что он позволяет только ссылке (указателю) быть постоянной. Упомянутая (указанная) вещь все еще может быть изменена. Это сложная часть, но выхода нет. Реализация постоянных объектов означает, что они не должны предоставлять какие-либо изменяемые методы или свойства, но это неудобно.
См. Также Эффективный C #: 50 конкретных способов улучшить свой C # (Правило 2 - Предпочитайте константу только для чтения).
источник