Публичный список без добавления

public class RegistrationManager
{
  public List<object> RegisteredObjects;

  public bool TryRegisterObject(object o) 
  {
    // ...
    // Add or not to Registered
    // ...
  }
} 

Я хочу чтобы RegisterObjects быть доступным извне класса, но и это единственный способ заполнить RegisterObjects список через TryRegisterObject(object o),

Это возможно?

5 ответов

Решение

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

public class RegistrationManager
{
  private List<object> _registeredObjects;
  ReadOnlyCollection<object> _readOnlyRegisteredObjects;

  public RegistrationManager()
  {
      _registeredObjects=new List<object>();
      _readOnlyRegisteredObjects=new ReadOnlyCollection<object>(_registeredObjects);
  }

  public IEnumerable<object> RegisteredObjects
  {
     get { return _readOnlyRegisteredObjects; }
  }


  public bool TryRegisterObject(object o) 
  {
    // ...
    // Add or not to Registered
    // ...
  }
} 

Скройте это под IEnumerable. Вы получите коллекцию "только для чтения" в классе и будете работать со списком внутри:

public class RegistrationManager
{
  public IEnumerable<object> RegisteredObjects
  {
    get
    {
      return _registeredObjects;
    }
  }
  private List<object> _registeredObjects;

  public bool TryRegisterObject(object o) 
  {
    // ...
    // Add or not to Registered
    // ...
  }
} 

Более защищенный вариант с IReadOnlyColection:

public class RegistrationManager
{
    public IReadOnlyCollection<object> RegisteredObjects
    {
        get { return new ReadOnlyCollection<object>(_registeredObjects); }
    }
    private List<object> _registeredObjects;

    public bool TryRegisterObject(object o)
    {
        // ...
        // Add or not to Registered
        // ...
    }
}

Нечто подобное (я полагаю, у вас должен быть доступ только для чтения, что означает, что Add, RemoveAt, Clear и т.д. не допускаются)

public class RegistrationManager
{
  // change RegisteredObjects to be private
  //TODO: do you really want List<object> instead of, say, List<RegisteredItem>?
  private List<object> RegisteredObjects = new List<object>();

  // let RegisteredObjects be visible as read-only
  public IReadOnlyList<object> Items { 
    get {
      return RegisteredObjects;
    }
  }

  // your TryRegisterObject
  public bool TryRegisterObject(object o) 
  {
    // ...
    // Add or not to Registered
    // ...
  }
} 

Недостатком решения является то, что технически возможно отбросить, например,

  RegistrationManager manager = ...

  // you can't do this
  // manager.Items.Add(new Object()); // <- compile time error
  // but can do this
  ((List<Object>) (manager.Items)).Add(new Object());

Вернуть как IReadOnlyList

public class RegistrationManager
{
   private List<object> _registeredObjects;
   public IReadOnlyList<object> RegisteredObjects
   {
       get{  return _registeredObjects; }
   }
   public bool TryRegisterObject(object o) 
   {
      // ...
      // Add or not to Registered
      // ...
   }
 } 

Да, вы можете предоставить свойство типа IReadOnlyCollection (T).

List (T) реализует IReadonlyCollection(T)

public class RegistrationManager
{
   private List<object> _registeredObjects; 
   public IReadOnlyCollection<object> RegisteredObjects
   {
      get
      {
         return _registeredObjects as IReadOnlyCollection<object>;
      }
   } 
}
Другие вопросы по тегам