Public List without Add

1.9k Views Asked by At
public class RegistrationManager
{
  public List<object> RegisteredObjects;

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

I want that RegisterObjects be accessible from outside of the class, but also that the only way to populate the RegisterObjects list is through TryRegisterObject(object o).

Is this possible ?

5

There are 5 best solutions below

3
On BEST ANSWER

I would hide it under ReadonlyCollection. In this case client won't be able to add elements via casting to IList for example. It totaly depends on how secure you want to be (in simplest scenario exposing IEnumerable will be pretty enough).

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
    // ...
  }
} 
2
On

Hide it under IEnumerable. You'll get "readonly" collection outise the class and work with List inside:

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

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

More protected variant with 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
        // ...
    }
}
1
On

Something like that (I guess you have to have read-only access which means that Add, RemoveAt, Clear etc. are not allowed):

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
    // ...
  }
} 

downside of the solution is that, technically, it's possible to cast back, e.g.

  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());
0
On

return it as 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
      // ...
   }
 } 
0
On

Yes you can expose a property of type IReadOnlyCollection(T).

List(T) implements IReadonlyCollection(T)

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