Reputation: 49
How would I create a property in a class that can only be set using an addition assignment. I know events work this way in C#. I was wondering how I may implement the construct in my own code.
Eg. For Events I can do the following
public event EventHandler myEventHandler;
myEventHandler += NewEvent;
And that will add NewEvent
to the chain of events that gets run when myEventHandler
is called.
I want to be able to do something similar. I want to create a Graph
class which models mathematical graphs with nodes and connections. The Graph
class would have a nodes
property which should only be able to have nodes added or removed but not set as a whole property.
Once again using the EventHandler
example, I can't do the following with EventHandler
myEventHandler = OnlyOneEventWillRun;
I also want to be able to implement logic to the addition assignment similar to the set{}
accessor.
Upvotes: 1
Views: 173
Reputation: 21917
The Graph class would have a nodes property which should only be able to have nodes added or removed but not set as a whole property.
While this is great for encapsulation, there are simpler and more obvious ways to implement it than overloading the +=
operator.
Here is one example:
class Graph
{
private List<Node> nodes;
public ReadOnlyCollection<Node> Nodes
{
get { return new ReadOnlyCollection<Node>(nodes); }
//note no setter
}
public void AddNode(Node node)
{
//whatever additional logic you need
nodes.Add(node);
}
}
If you want to make your API more fluent, you could return the Graph
object itself as the return value from AddNode
, so it could be used with chained adds:
graph.AddNode(node1)
.AddNode(node2)
.AddNode(node3);
And/or accept a params
array parameter for the node(s) so that it could be called as:
graph.AddNode(node1, node2);
graph.AddNode(node3);
Upvotes: 1
Reputation: 3001
For starters, myEventHandler
is a multicast delegate - you can make your own to mirror that functionality, but that doesn't really solve your problem as you stated.
The approach I would take is to use a private setter (or no setter at all) - this would allow you to set the value from within the class that defines the property (where presumably you will know and remember what you are doing) but not from outside the class (where another developer could unwittingly screw it up):
private List<object> _nodes; // private backing field
public List<object> Nodes
{
get
{
return _nodes; // can be "gotten" by any class
}
private set // can only be set from within this class
{
if (value != _nodes)
{
// do additional logic
_nodes = value; // set the backing variable
}
}
}
public void AddNode(object Node)
{
Nodes.Add(Node);
}
public void RemoveNode(object Node)
{
Nodes.Remove(Node);
}
Upvotes: 2