I think the most common way of adding something to a collection is to use some kind of Add
method that a collection provides:
class Item {}
var items = new List<Item>();
items.Add(new Item());
and there is actually nothing unusual about that.
I wonder however why don't we do it this way:
var item = new Item();
item.AddTo(items);
it seems to be somehow more natural then the first method. This would have the andvantange that when the Item
class has a property like Parent
:
class Item
{
public object Parent { get; private set; }
}
you can make the setter private. In this case of course you cannot use an extension method.
But perhaps I'm wrong and I've just never seen this pattern before because it's so uncommon? Do you know whether there is any such pattern?
In C#
an extension method would be useful for that
public static T AddTo(this T item, IList<T> list)
{
list.Add(item);
return item;
}
How about other languages? I guess in most of them the Item
class had to provide a let's call it ICollectionItem
interface.
Update-1
I've been thinking about it a little bit more and this pattern would be really usefull for example if you don't want an item to be added to multiple collections.
test ICollectable
interface:
interface ICollectable<T>
{
// Gets a value indicating whether the item can be in multiple collections.
bool CanBeInMultipleCollections { get; }
// Gets a list of item's owners.
List<ICollection<T>> Owners { get; }
// Adds the item to a collection.
ICollectable<T> AddTo(ICollection<T> collection);
// Removes the item from a collection.
ICollectable<T> RemoveFrom(ICollection<T> collection);
// Checks if the item is in a collection.
bool IsIn(ICollection<T> collection);
}
and a sample implementation:
class NodeList : List<NodeList>, ICollectable<NodeList>
{
#region ICollectable implementation.
List<ICollection<NodeList>> owners = new List<ICollection<NodeList>>();
public bool CanBeInMultipleCollections
{
get { return false; }
}
public ICollectable<NodeList> AddTo(ICollection<NodeList> collection)
{
if (IsIn(collection))
{
throw new InvalidOperationException("Item already added.");
}
if (!CanBeInMultipleCollections)
{
bool isInAnotherCollection = owners.Count > 0;
if (isInAnotherCollection)
{
throw new InvalidOperationException("Item is already in another collection.");
}
}
collection.Add(this);
owners.Add(collection);
return this;
}
public ICollectable<NodeList> RemoveFrom(ICollection<NodeList> collection)
{
owners.Remove(collection);
collection.Remove(this);
return this;
}
public List<ICollection<NodeList>> Owners
{
get { return owners; }
}
public bool IsIn(ICollection<NodeList> collection)
{
return collection.Contains(this);
}
#endregion
}
usage:
var rootNodeList1 = new NodeList();
var rootNodeList2 = new NodeList();
var subNodeList4 = new NodeList().AddTo(rootNodeList1);
// Let's move it to the other root node:
subNodeList4.RemoveFrom(rootNodeList1).AddTo(rootNodeList2);
// Let's try to add it to the first root node again...
// and it will throw an exception because it can be in only one collection at the same time.
subNodeList4.AddTo(rootNodeList1);
item.AddTo(items)
suppose you have a language without extension methods: natural or not, to support addTo every type would need this method and provide it for every type of collection supporting appending. That is like the best example of introducing dependencies between everything I've ever heard :P - I think the false premise here is trying to model some programming abstraction to 'real' life. That often goes wrong.add(item, collection)
, but that's not good OO style.