C # возвращает переменную только для чтения из get; задавать; - PullRequest
33 голосов
/ 02 июня 2009

Клянусь, я видел пример этого, но немного погуглил и не могу его найти.

У меня есть класс, который имеет ссылку на объект и должен иметь GET; метод для этого. Моя проблема в том, что я не хочу, чтобы кто-то мог возиться с этим, т. Е. Я хочу, чтобы они получили версию только для чтения (заметьте, что я должен иметь возможность изменять ее из своего класса).

Спасибо

Ответы [ 7 ]

52 голосов
/ 02 июня 2009

Нет, это невозможно. Например, если вы вернете List<string> (и он не является неизменным), то вызывающие абоненты смогут добавить записи.

Обычный способ обойти это вернуть неизменная обертка, например, ReadOnlyCollection<T>.

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

Обратите внимание, что простое возвращение неизменяемого представления интерфейса (например, возвращение IEnumerable<T> вместо List<T>) не остановит вызывающую функцию от возврата к изменяемому типу и изменения.

РЕДАКТИРОВАТЬ: обратите внимание, что помимо всего прочего, этот вид беспокойства является одной из причин, по которой неизменяемые типы облегчают анализ кода:)

6 голосов
/ 02 июня 2009

Возвращает ссылку на урезанный интерфейс:

 interface IFoo
   string Bar { get; }

 class ClassWithGet
   public IFoo GetFoo(...);
3 голосов
/ 02 июня 2009

Если объект не слишком сложный / обширный, напишите обертку вокруг него.

например:

class A {
    public string strField = 'string';
    public int intField = 10;
}

class AWrapper {
    private A _aObj;

    public AWrapper(A aobj) {
      _aObj = A;
    }

    public string strField {
         get {
            return _aObj.strField;
         }
    }

    public int intField {
         get {
            return _aObj.intField;
         }
    }
}

Итак, теперь все, что вы делаете, - это передаете своему клиентскому коду экземпляр класса AWrapper, чтобы они могли использовать только то, что вы позволяете им видеть.

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

3 голосов
/ 02 июня 2009

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

2 голосов
/ 07 января 2014

Ваш вопрос читается так, как вы ищете:

public PropertyName { get; private set; }

Но тогда, учитывая ответы до сих пор, я не уверен, что правильно истолковал ваш вопрос. Кроме того, кто я такой, чтобы допросить Джона Скита? :)

0 голосов
/ 21 марта 2016

Я столкнулся с этой проблемой определенным образом. У меня есть класс CategoryViewModel, у которого есть свойство Category, которое я хочу, чтобы частный доступ только для чтения:

public CategoryViewModel
{
    private Category { get; }

}

На самом деле, я хочу, чтобы он экспортировался как доступный только для чтения в другой класс. Однако я не могу сделать такую ​​вещь. В моем случае (может быть, это поможет некоторым другим парням), я хочу добавить его в репозиторий. Единственный способ, который я нашел, - это использовать функцию с хранилищем в качестве параметра 1 и действие в качестве параметра 2:

public void ApplyAction(ICategoryRepository repo, Action<ICategoryRepository, Category> action)
{
    action(repo, Category);
}

Таким образом, из других мест, я могу сделать такую ​​вещь:

 categoryViewModel.ApplyAction(_repository, (r, c) => r.MarkForInsertOrUpdate(c));

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

0 голосов
/ 22 июня 2012

Я согласен с ReadOnlyCollection

Смотрите мой простой код:

 private List<Device> _devices;
public readonly System.Collections.ObjectModel.ReadOnlyCollection<Device> Devices 
{
 get
 { 
return (_devices.AsReadOnly());
 } 

}

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

...