переменная, которая не может быть изменена

c# .net variables constants readonly

13427 просмотра

9 ответа

Разрешает ли C # переменную, которую нельзя изменить? Это похоже на a const, но вместо того, чтобы присваивать ей значение при объявлении, переменная не имеет никакого значения по умолчанию, но может быть назначена только один раз во время выполнения (EDIT: и, возможно, не из конструктора). или это невозможно?

Автор: Louis Rhys Источник Размещён: 12.11.2019 09:43

Ответы (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:21

12 плюса

Вы можете объявить readonlyпеременную, которую можно установить только в конструкторе или непосредственно через ее объявление.

Автор: Oliver Hanappi Размещён: 07.09.2010 08:19

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:24

4 плюса

Конечно. Вы можете использовать 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:19

2 плюса

Поскольку аналогичный вопрос был недавно задан @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:34

1 плюс

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

Прочитайте об этом здесь: http://msdn.microsoft.com/en-us/library/acdd6hb7%28v=VS.100%29.aspx

Автор: Rune Grimstad Размещён: 07.09.2010 08:20

1 плюс

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

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

Автор: Paul Ruane Размещён: 07.09.2010 08:23

0 плюса

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

private myVariable = null;
public object MyVariable
{
   get { return myVariable; }
   set { if(myVariable == null ) myVariable = value;
}
Автор: Andy Rose Размещён: 07.09.2010 08:26
Вопросы из категории :
32x32