переменная, которая не может быть изменена
13427 просмотра
9 ответа
Разрешает ли C # переменную, которую нельзя изменить? Это похоже на a const
, но вместо того, чтобы присваивать ей значение при объявлении, переменная не имеет никакого значения по умолчанию, но может быть назначена только один раз во время выполнения (EDIT: и, возможно, не из конструктора). или это невозможно?
Ответы (9)
5 плюса
Вы можете создать свой собственный универсальный класс, который обеспечивает эту функциональность, но это может быть излишним.
public class SetValueOnce<T>
{
public bool _set;
private T _value;
public SetValueOnce()
{
_value = default(T);
_set = false;
}
public SetValueOnce(T value)
{
_value = value;
_set = true;
}
public T Value
{
get
{
if(!_set)
throw new Exception("Value has not been set yet!");
return _value;
{
set
{
if(_set)
throw new Exception("Value already set!");
_value = value;
_set = true;
}
}
}
Автор: Paul Hadfield
Размещён: 07.09.2010 08:35
24 плюса
Да, есть несколько способов сделать это в C #.
Во-первых, что такое «переменная»? Переменная является местом хранения. Локальные переменные, формальные параметры методов (и индексаторы, конструкторы и т. Д.), Статические поля и поля экземпляров, элементы массива и разыменования указателей являются переменными.
Некоторые переменные могут быть объявлены как «только для чтения». Переменная «только для чтения» может быть изменена только один раз, либо инициализатором в объявлении, либо в конструкторе. Только объявления полей могут быть только для чтения; C # не поддерживает объявленные пользователем локальные файлы только для чтения.
Существуют определенные ограничения на переменные только для чтения, которые помогают гарантировать, что нормальная работа C # не вносит мутации. Это может привести к неожиданным результатам! Видеть
http://ericlippert.com/2008/05/14/mutating-readonly-structs/
для деталей.
Некоторые местные жители также доступны для чтения. Например, когда вы говорите using(Stream s = whatever)
внутри встроенного оператора, using
вы не можете изменить значение s. Причина этого ограничения состоит в том, чтобы предотвратить ошибку, при которой вы создаете ресурс, который должен быть утилизирован, а затем утилизируете другой ресурс при удалении содержимого переменной s. Лучше быть таким же.
(К сожалению, в C # есть ошибки, связанные с ситуацией, когда располагаемый ресурс является структурным типом, структура имеет метод, который изменяет структуру, а локальная переменная является или не является закрытой локальной для анонимной функции или блока итератора; поскольку сценарии неясны, и исправление может быть нарушено, мы еще ничего не сделали, ожидая дальнейшего анализа.)
Локальная переменная, объявленная в foreach
выражении, также эффективна readonly
- эта переменная каждый раз меняет значение в цикле, но вы не можете изменять его значение.
Нет никакого способа сделать разбор только для формального параметра, элемента массива или указателя.
Существуют различные способы «снять» ограничение на чтение и запись в переменную, которая должна быть только для чтения. Вы можете использовать Reflection или небезопасный код, чтобы нарушить практически любое ограничение безопасности CLR, если у вас достаточно прав для этого. Если тебе больно, когда ты это делаешь, не делай этого; с этими полномочиями приходит ответственность знать, что вы делаете, и делать это правильно.
Автор: Eric Lippert Размещён: 07.09.2010 03:2112 плюса
Вы можете объявить readonly
переменную, которую можно установить только в конструкторе или непосредственно через ее объявление.
5 плюса
Вы можете бросить свой собственный, используя пользовательский установщик (но не используйте, Object
если вам не нужно, выберите правильный класс):
private Object myObj = null;
private Boolean myObjSet = false;
public Object MyObj
{
get { return this.myObj; }
set
{
if (this.myObjSet) throw new InvalidOperationException("This value is read only");
this.myObj = value;
this.myObjSet = true;
}
}
РЕДАКТИРОВАТЬ:
Это не останавливает частное поле, изменяемое внутренними объектами класса.
Автор: cjk Размещён: 07.09.2010 08:244 плюса
Конечно. Вы можете использовать readonly
:
То есть: public readonly int z;
Это можно изменить только из конструктора.
Из MSDN :
Вы можете присвоить значение полю только для чтения только в следующих контекстах:
Когда переменная инициализируется в объявлении, например:
public readonly int y = 5;
Для поля экземпляра в конструкторах экземпляров класса, который содержит объявление поля, или для статического поля в статическом конструкторе класса, который содержит объявление поля. Это также единственные контексты, в которых допустимо передавать поле только для чтения в качестве параметра
out
илиref
.
Однако, если вы хотите создать свойство, которое может быть изменено только внутри класса, который его создал, вы можете использовать следующее:
public string SetInClass
{
get;
private set;
}
Это позволяет вносить изменения внутри класса, но переменная не может быть изменена извне класса.
Автор: Kyle Rozendo Размещён: 07.09.2010 08:192 плюса
Поскольку аналогичный вопрос был недавно задан @Ivan , позвольте мне предложить еще один метод для создания экземпляра свойства в любом месте кода , конечно, точнее, с поддержкой универсального конструктора.
public class Immutable<T> {
public T Val { get; private set; }
public Immutable(T t) {
Val = t;
}
}
Использование будет
var immutableInt1 = new Immutable<int>(3); // you can set only once
immutableInt1.Val = 5; // compile error here: set inaccessible
Console.WriteLine("value: " + immutableInt1.Val);
Дело в том, что теперь вы получаете ошибку компиляции, если вы пытаетесь установить новое значение.
Кроме того, я считаю, что вам лучше использовать функциональный язык, такой как F #, а не C #, если вы хотите следовать этой парадигме.
Автор: user6996876 Размещён: 21.03.2017 08:341 плюс
Вы можете определить переменную только для чтения, значение которой может быть установлено только в конструкторе объектов.
Прочитайте об этом здесь: http://msdn.microsoft.com/en-us/library/acdd6hb7%28v=VS.100%29.aspx
Автор: Rune Grimstad Размещён: 07.09.2010 08:201 плюс
Можно пометить поле, readonly
которое потребует, чтобы вы установили его значение либо в точке объявления, либо в конструкторе, а затем предотвратит его переназначение после построения.
Однако, хотя ссылка будет доступна только для чтения, объект не обязательно будет таким же. Чтобы предотвратить изменение самого объекта, вам нужно сделать тип неизменяемым или же предоставить класс-оболочку, который предоставляет только неразрушающие методы и свойства базового типа.
Автор: Paul Ruane Размещён: 07.09.2010 08:230 плюса
Если вы хотите назначить переменную во время выполнения после того, как объект, содержащий ее, был создан, вы можете использовать пользовательское свойство с методом установки, которое можно изменить только один раз. то есть.
private myVariable = null;
public object MyVariable
{
get { return myVariable; }
set { if(myVariable == null ) myVariable = value;
}
Автор: Andy Rose
Размещён: 07.09.2010 08:26
Вопросы из категории :
- c# Преобразовать десятичную в двойную?
- c# Как рассчитать чей-то возраст в C #?
- c# Как вы сортируете словарь по значению?
- c# В чем разница между int и Integer в Java и C #?
- .net Как создать новый экземпляр объекта из Типа
- .net Действительно ли опечатанные классы действительно предлагают преимущества?
- variables Какой лучший способ вернуть несколько значений из функции в Python?
- variables Create a variable in .CSS file for use within that .CSS file
- variables Можно ли напечатать тип переменной в стандартном C ++?
- variables Как работают закрытия JavaScript?
- constants В чем разница между const и readonly в C #?
- constants Создание постоянного словаря в C #
- constants Должен ли я использовать мои константы с заглавной буквы?
- constants Где я могу найти список констант Windows API
- readonly Каковы преимущества пометки поля как «только для чтения» в C #?
- readonly В форме Django как сделать поле доступным только для чтения (или отключенным), чтобы его нельзя было редактировать?
- readonly Создайте поле внешнего ключа в форме django только для чтения и по-прежнему разрешайте отправку формы