Reputation: 2630
I am wondering what is the best way to use properties when dealing with collections.
For example I have a class Foo and I want to have a list of that class stored. Which of the following should be used:
private List<Foo> myList;
private List<Foo> myOtherList = new List<Foo>();
now for the property:
public List<Foo> ListOfFoo
{
get
{
return myList;
}
set
{
myList= new List<Foo>(value);
}
}
Or should the set just be to the value?
public List<Foo> ListOfFoo
{
get
{
return myList;
}
set
{
myList= value;
}
}
Upvotes: 3
Views: 239
Reputation: 3799
Why not use the IEnumerator-Interface on the class and if you have to use a setter, use a certain method.
This way you are hiding the actual List-Implementation as well.
class FooBar : IEnumerator
{
private Collection<Foo> col;
public IEnumarator GetEnumerator()
{
return col.GetEnumerator();
}
public void SetList(Collection col)
{
this.col= col; // you can also make this more general and convert the parameter so it fits your listimpl.
}
}
class Clazz
{
private void WhatEver(){
FooBar foobar = new FooBar();
...
foreach(Foo f in foobar)
{...}
}
}
Upvotes: 0
Reputation: 41146
Generally, expose only an Interface (ICollection, IList or similar), and make it readonly:
private IList<Foo> m_list = new List<Foo>();
public IList<Foo> List {get { return m_list; } }
Advantage: You can modify the implementation, e.g. switch from a List to an Observable List. You might need to make the m_list
member of the concrete type rather than the interface, e.g. to use additional funcitonality.
With an settable external list, you run into a few problems. However, there are some cases where this is needed:
Upvotes: 0
Reputation: 18178
It depends.
When the first style is used, you create a copy of the list, which is generally unnecessary. .Net convention is for the setter to assign the reference to the property. This is why I would lean towards the second option.
However, if you are intending for the copy operation to take place, the first option is what you are looking for.
Upvotes: 0
Reputation: 51739
Choose
private List<Foo> myOtherList = new List<Foo>();
becuse the other just declares a reference (which is set to null), the sample above declares a reference to a list, creates a list and assignes that new list to the reference.
Choose
public List<Foo> ListOfFoo
{
get { return myList; }
set { myList= new List<Foo>(value); }
}
When you want myList to NOT refelect any changes that happen to the list after it is assigned to myList e.g.
List<string> myFirstList = new List<string>();
myFirstList.Add("Hello");
myFirstList.Add("World");
List<string> mySecondList = new List<string>(myFirstList);
// mySecondList now contains Hello & world
myFirstList.Add("Boyo");
// myFrist List now contains Hello, world & Boyo
// mySecondList still contains Hello & world
Choose
public List<Foo> ListOfFoo
{
get { return myList; }
set { myList= value; }
}
When you want both references to point to the same object e.g.
List<string> myFirstList = new List<string>();
myFirstList.Add("Hello");
myFirstList.Add("World");
List<string> mySecondList = myFirstList;
// mySecondList now contains Hello & world
myFirstList.Add("Boyo");
// myFrist List now contains Hello, world & Boyo
// mySecondList "also" contains Hello, world & Boyo
The "also" above is in quotes, because actually, there is only one list, and both my first and my second point to the same list.
Upvotes: 2
Reputation: 42182
Generally you don't want to use properties of a rich type like List<T>
(normally one would use Collection<T>
), and generally properties of a collection type are read-only - the collection itself can be modified with methods like Clear
, Add
etc., and this is normally sufficient.
For example:
class Foo
{
Collection<Bar> _bars = new Collection<Bar>();
public Collection<Bar> Bars { get { return _bars; } }
}
This also leaves you open to validate modifications to the collection by implementing a descendant of Collection<T>
and overriding the InsertItem
, SetItem
etc. methods.
Upvotes: 2