2013-06-21 2 views
1

Я пишу библиотеку, которую будут использовать другие разработчики в нашей компании. Базовый класс конечного автомата имеет ReadOnlyCollection<T> разрешенных состояний и т. Д. Разработчики должны наследовать от этого класса и устанавливать разрешенные состояния.Установка объекта только для чтения из производного класса

Я хочу ограничить их инициализацией ReadOnlyCollection<T> в конструкторе их производных классов и не в состоянии его модифицировать позже.

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

Я предполагаю, что это не очень редкий сценарий. Любой элегантный способ добиться этого, если разработчики переопределяют ReadOnlyCollection<T>?

ответ

3

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

public class BaseClass 
{ 
     protected readonly Collection someObject; 
     public BaseClass(Collection object) 
     { 
      someObject = object 
     } 
} 

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

public class Derivedclass : BaseClass 
{ 
     public DerivedClass() : base(/*pass the collection object here*/) 
     { 
     } 
} 

Еще есть яма падение в этом, если вы получите ссылку коллекции, вы можете изменить коллекцию с помощью вызова Добавить или удалить метод сбора в производном классе только вещь, вы не можете REINITIALIZE если он только что прочитан.

0

Это должно быть ReadOnlyCollection? Я бы пошел на IEnumerable.

Это может быть сделано, как это, похоже на srsyogesh's ответ:

public abstract class StateMachine 
{ 
    public StateMachine(params States[] allowedStates) 
    { 
     _allowedStates = allowedStates; 
    } 

    private readonly IEnumerable<States> _allowedStates; 

    public IEnumerable<States> AllowedStates 
    { 
     get { return _allowedStates; } 
    } 
} 

public class DerivedStateMachine : StateMachine 
{ 
    public DerivedStateMachine() 
     : base(States.State1, States.State2) 
    { 

    } 
} 

Конечно, можно было бы еще бросить собственности обратно в массив и изменить его, но это было бы своего рода преступника. Зависит от вашей аудитории. Чтобы быть более пуленепробиваемым, вы могли вместо того, чтобы просто возвращать поле, перебирать содержимое:

public IEnumerable<States> AllowedStates 
    { 
     get 
     { 
      foreach(var state in _allowedStates) 
       yield return state; 
     } 
    }