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.
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);
}
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);
Related
I'm reading CLR via C# by Jeffrey Richter which says:
public event EventHandler<NewMailEventArgs> NewMail;
When the C# compiler compiles the line above, it translates this single line of source code into the
following three constructs:
private EventHandler<NewMailEventArgs> NewMail = null;
// 2. A PUBLIC add_Xxx method (where Xxx is the Event name)
public void add_NewMail(EventHandler<NewMailEventArgs> value) {
... // use Delegate.Combine internally
}
// 3. A PUBLIC remove_Xxx method (where Xxx is the Event name) allows methods to unregister interest in the event.
public void remove_NewMail(EventHandler<NewMailEventArgs> value) {
... // use Delegate.Remove internally
}
and the author says:
The System.Windows.Forms.Control type defines about 70 events. If the Control type implemented the events by allowing the compiler to implicitly generate the add and remove accessor methods and delegate fields, every Control object would have 70 delegate fields in it just for the events! Because most programmers care about just a few events, an enormous amount of memory would be wasted for each object created from a Control-derived type. To efficiently store event delegates, each object that exposes events will maintain a collection (usually a dictionary) with some sort of event identifier as the key and a delegate list as the value.
So for example, we should explicitly implementing an event in a type as:
public sealed class EventKey { }
public sealed class EventSet {
private readonly Dictionary<EventKey, Delegate> m_events = new Dictionary<EventKey, Delegate>();
// Adds an EventKey -> Delegate mapping if it doesn't exist or combines a delegate to an existing EventKey
public void Add(EventKey eventKey, Delegate handler) {
...
}
// Removes a delegate from an EventKey (if it exists) and
// removes the EventKey -> Delegate mapping if the last delegate is removed
public void Remove(EventKey eventKey, Delegate handler) {
...
}
// Raises the event for the indicated EventKey
public void Raise(EventKey eventKey, Object sender, EventArgs e) {
... // use Delegate.DynamicInvoke internally
}
}
public class TypeWithLotsOfEvents {
private readonly EventSet m_eventSet = new EventSet();
protected static readonly EventKey s_fooEventKey = new EventKey();
public event EventHandler<FooEventArgs> Foo {
add { m_eventSet.Add(s_fooEventKey, value); }
remove { m_eventSet.Remove(s_fooEventKey, value); }
}
...
}
I don't why this approach is more efficient, it still need to declare each event it contains, and for derived types of TypeWithLotsOfEvents, the child instances will contain all the parent's delegate fields, so nothing you can save? Taking the windows form control type which contains 70 events, any derived control type will have to contain 70 events as well because the inheritance hierarchy
The important thing to note here is that this...
public event EventHandler<FooEventArgs> Foo {
add { m_eventSet.Add(s_fooEventKey, value); }
remove { m_eventSet.Remove(s_fooEventKey, value); }
}
does not generate any fields.
This generates only two methods:
private void add_Foo(EventHandler<FooEventArgs> value) {
m_eventSet.Add(s_fooEventKey, value);
}
private void remove_Foo(EventHandler<FooEventArgs> value) {
m_eventSet.Remove(s_fooEventKey, value);
}
This is rather similar to how auto-implemented properties generate a backing-field plus a getter and setter method, whereas non-auto-implemented properties generate only the getter and setter methods.
Note that you would still have the field s_fooEventKey, but that one is static, so there is only one instance of it ever, rather than one instance of the field per instance of TypeWithLotsOfEvents. So we are all fine.
Try using reflection to print out the private fields of Control. You will see that it doesn't fields that correspond to its events. On the other hand, if you write your own class without using the "dictionary of events" approach, and try to print out its fields, you will see there is a field for each event you declare.
We have some classes where we need to fire events during initialization. The current state is that we use emtpy ctors, then attach all the events we need and then use init() to fully initialize the object.
Id like to get rid of this two-phase-initialization. Its ugly and causes problems when using the objects without initialization (we tried the 'isInitialized' flag, but that ugly too...).
Is there a better way to attach events to an object which are needed during initialization?
Edit:
Its code like this:
public class ExampleClass {
public int value;
public event ErrorHandling OnError;
public ExampleClass(int value) {
this.value = value;
}
void init() {
// do something with that value
OnError?.Invoke(value); // something went wrong
}
}
int main() {
ExampleClass example = new ExampleClass(2);
example.OnError += // some error handling
example.init();
}
Its a very limited example. But in fact I cant get rid of the events during initialization.
TIA
Do you need to use events? Either pass an IErrorHandler into the constructor (ideally with dependency injection), or like pass an Action that will be run instead of the event
Need help calling event from another class.
I have class with declared event:
public class MxPBaseGridView : GridView
{
public event AddNewItemsToPopUpMenuEventHandler AddNewItemsToPopUpMenu;
...
}
Another class from which i need to call event has methods and "AddNewItemsToPopUpMenuEventHandler " delegate
public delegate void AddNewItemsToPopUpMenuEventHandler(PopupMenuShowingEventArgs e);
public static class GridViewUtils
{
public static void gridView_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e)
{
if (e.MenuType != DevExpress.XtraGrid.Views.Grid.GridMenuType.Row)
{
if (menu != null)
{
if (sender is MxPBaseAdvBandedGridView)
{
MxPBaseAdvBandedGridView currentGrid = sender as MxPBaseAdvBandedGridView;
...
currentGrid.AddNewItemsToPopUpMenu();
if (currentGrid.AddNewItemsToPopUpMenu != null) //there i need to call event
currentGrid.AddNewItemsToPopUpMenu(e); // how you understand it doesn't work
}
so what is the right way to do the same job?
Events in C# are kind of funny things. They're very much like automatic properties, but with a private get method and a public (or whatever access you choose) set method.
Allow me to demonstrate. Let's create a hypothetical class with a hypothetical event.
class SomeObject{
public event EventHandler SomeEvent;
public void DoSomeStuff(){
OnSomeEvent(EventArgs.Empty);
)
protected virtual void OnSomeEvent(EventArgs e){
var handler = SomeEvent;
if(handler != null)
handler(this, e);
}
}
This class follows the typical pattern for a class that exposes an event. It exposes the event publicly, but has a protected virtual "On..." method that, by default, simply calls the event (if it has any subscibers). This protected virtual method not only encapsulates the logic of actually calling the event, but provides a way for derived classes to:
conveniently handle the event with less overhead,
perform some processing before or after all external subscribers receive the event,
call an entirely different event, or
suppress the event altogether.
But what is this "event" object called SomeEvent? In C#, we're familiar with fields, properties, and methods, but what exactly is an event?
Before we get into that, it helps to realize that there are really only two types of class members in C#: fields and methods. Properties and events are more or less just syntactic sugar on top of those.
A property is really either one or two methods, and a name stored in metadata that the C# compiler allows you to use to refer to one of those two methods. That is, when you define a property like this one:
public string SomeProperty{
get{return "I like pie!";}
set{
if(string.Compare(value, "pie", StringComparison.OrdinalIgnoreCase) == 0)
Console.WriteLine("Pie is yummy!");
else Console.WriteLine("\"{0}\" isn't pie!", value ?? "<null>");
}
}
the compiler writes two methods for you:
public string get_SomeProperty(){return "I like pie!";}
public void set_SomeProperty(string value){
if(string.Compare(value, "pie", StringComparison.OrdinalIgnoreCase) == 0)
Console.WriteLine("Pie is yummy!");
else Console.WriteLine("\"{0}\" isn't pie!", value ?? "<null>");
}
I don't mean this obliquely. These two methods literally become part of your compiled class along with a chunk of metadata about the property, which tells the compiler next time which methods to call when the property is read from (get) or written to (set). So when you write code like this:
var foo = someObject.SomeProperty;
someObject.SomeProperty = foo;
The compiler finds the getter and setter methods assigned to SomeProperty, and turns your code into:
string foo = someObject.get_SomeProperty();
someObject.set_SomeProperty(foo);
This is why if you define a class with a public field, but later decide to change it to a property so that you can do something interesting when it is read from or written to, you have to recompile any external assemblies that contain references to this member, because what was a field access instruction needs to become a method call instruction, instead.
Now this property was somewhat abnormal, in that it didn't rely on any backing field. Its getter returned a constant value, and its setter didn't store its value anywhere. To be clear, that's perfectly valid, but most of the time, we define properties more like this:
string someProperty;
public string SomeProperty{get{return someProperty;}set{someProperty = value;}}
This property doesn't do anything other than read and write to a field. It's pretty much the same as a public field named SomeProperty, except that you could add logic to that getter and setter at a later date, without making consumers of your class recompile. But this pattern is so common, that C# 3 added "automatic properties" to achieve the same effect:
public string SomeProperty{get;set;}
The compiler turns this into the same code as we wrote above, except that the backing field has a super secret name that only the compiler knows, so we can only refer to the property in our code, even within the class itself.
Because the backing field is inaccessible to us, while you might have read-only properties like this:
string someProperty;
public string SomeProperty{get{return someProperty;}}
you'll almost never see read-only automatic properties (the compiler lets you write them, but you'll find very little use for them):
public string SomeProperty{get;} // legal, but not very useful unless you always want SomeProperty to be null
Instead, what you'll usually see is this:
public string SomeProperty{get;private set;}
The private access modifier attached to set makes it possible for methods within the class to set the property, but the property still appears read-only outside the class.
"Now what does any of this have to do with events?" you may ask. Well, as a matter of fact, an event is very much like an automatic property. Normally, when you declare an event, the compiler generates a super secret backing field and a pair of methods. Except that the backing field isn't quite as super secret, and the pair of methods aren't "get" and "set", they're "add" and "remove". Let me demonstrate.
When you write an event like this:
public event EventHandler SomeEvent;
what the compiler writes is this:
EventHandler SomeEvent;
public void add_SomeEvent(EventHandler value){
SomeEvent = (EventHandler)Delegate.Combine(SomeEvent, value);
}
public void remove_SomeEvent(EventHandler value){
SomeEvent = (EventHandler)Delegate.Remove(SomeEvent, value);
}
It also adds some metadata glue so that later, when you write code like this:
void Awe_SomeEventHandler(object sender, EventArgs e){}
void SomeMethod(SomeObject Awe){
Awe.SomeEvent += Awe_SomeEventHandler
Awe.SomeEvent -= Awe_SomeEventHandler
}
the compiler rewrites it as (only the interesting lines):
Awe.add_SomeEvent(Awe_SomeEventHandler);
Awe.remove_SomeEvent(Awe_SomeEventHandler);
What's important to take note of here is that the only publicly accessible members related to SomeEvent are those add and remove methods, and those are called when you use the += and -= operators. The backing field, that delegate object named SomeEvent that holds the event's subscribers, is a private field that only members of the declaring class can access.
However, much like the way automatic properties are only a shortcut for writing the backing field and getter and setter by hand, you can explicitly declare your delegate and add and remove methods as well:
internal EventHandler someEvent;
public event EventHandler SomeEvent{
add{someEvent = (EventHandler)Delegate.Combine(someEvent, value);}
remove{someEvent = (EventHandler)Delegate.Remove(someEvent, value);}
}
Then, other classes within your assembly can trigger your event:
var handler = Awe.someEvent;
if(handler != null)
handler(Awe, EventArgs.Empty);
However, it's easier and more idiomatic to define your event the normal (automatic) way, and just expose a "Raise" method:
internal void RaiseSomeEvent(){OnSomeEvent(EventArgs.Empty);}
But now you hopefully understand why you have to do it this way, and what's going on in the background.
You can only invoke an event in the class where you have defined the event. What is common is to use a specific method to fire the event, which you have to add in the class where you define the event. In your case, in the class MxPBaseGridView. Add the following:
public void OnAddNewItemsToPopUpMenu(<eventargstype> e) {
var addNewItemsToPopUpMenu = AddNewItemsToPopUpMenu;
if (addNewItemsToPopUpMenu != null)
addNewItemsToPopUpMenu(this, e);
}
Note: I'm not sure what the eventargs-type is, so I've left it open.
Then you can call this method from your static method.
Note: normally I define the On... methods as private, if necessary as protected. In this case I've defined it public since you need to call it from outside your class.
Here is the code for custom event args. I am confuse about use of those and also role of those. I can not understand this property public object AddedObject { get; private set; } the code is here :
public class ObjectAddedEventArgs : EventArgs
{
public ObjectAddedEventArgs(object addedObject)
{
AddedObject = addedObject;
}
public object AddedObject { get; private set; }
}
I can not understand use of the get and set property of added object. Please explain to me.
The AddedObject property is what is called an "auto property", which simply means that the C# compiler will generate a private variable to hold the value of the property. The "get" is the mechanism which allows you to read the value of the property. The "set" is the mechanism which allows you to set the value of the property, although in this case since the set is private you aren't able to set the value. This translates to code which would look roughly like this:
private object _AddedObject;
public object AddedObject
{
get { return this._AddedObject; }
private set { this._AddedObject = value; }
}
The class itself (the ObjectAddedEventArgs class) is used to provide additional data (the AddedObject value) to an event handler which, presumably, would access that data and do something with it as part of it's response to the event.
As per Microsoft's documentation:
EventArgs is the base class for classes containing event data.
....
This class contains no event data; it is used by events that do not
pass state information to an event handler when an event is raised. If
the event handler requires state information, the application must
derive a class from this class to hold the data.
That being said, the original developer of that class intended to handle events and at the same time making the object AddedObject available to the event handler method. See the website above for a nice example.
the good thing when you declare your events like this
event EventHandler<ObjectAddedEventArgs> MyObjectAddedEvent;
you can subscribe to it in a weak manner easily
myObjectInstance.MyObjectAddedEvent += new EventHandler<ObjectAddedEventArgs>(MyObjectAddedEventMethod).MakeWeak(eh => d.MyObjectAddedEvent -= eh);
private void MyObjectAddedEventMethod(object sender, ObjectAddedEventArgseventargs)
{
//do something with the event args
}
the weak stuff you find here.
If I have a property:
public list<String> names { get; set; }
How can I generate and handle a custom Event for arguments sake called 'onNamesChanged' whenever a name gets added to the list?
A BindingList is likely your best option as it has builtin change tracking and a variety of existing events you can use. Below is an example of exposing a custom event for Add which forwards to the BindingList event.
class Example
{
private BindingList<string> m_names = new BindingList<string>();
public IEnumerable<string> Names { get { return m_names; } }
public event AddingNewEventHandler NamesAdded
{
add { m_names.AddingNew += value; }
remove { m_names.AddingNew -= value; }
}
public void Add(string name)
{
m_names.Add(name);
}
}
You should check out the System.ComponentModel.BindingList, specifically the ListChanged event.
One alternative to BindingList is ObservableCollection - in this case you'd want to subscribe your own event handler to the CollectionChanged event and fire your event depending on the action.
David Mohundro shows one approach; one other option is to inherit from Collection<T> and override the various methods:
class Foo {}
class FooCollection : Collection<Foo>
{
protected override void InsertItem(int index, Foo item)
{
// your code...
base.InsertItem(index, item);
}
protected override void SetItem(int index, Foo item)
{
// your code...
base.SetItem(index, item);
}
// etc
}
Finally, you could create your own list (IList, IList<T>) from first principles - lots of work, little benefit.
A non-orthodox approach might be using an AOP framework such as PostSharp to "weave" a handler before/after the accessor is called, which fires an event.
You create an external class which contains the pre and/or post handling code for when your property is accessed, check if the value of the property changed between pre and post, and raise an event.
Bear in mind that while taking the value for comparison (inside your handler code), you might get into an infinite loop (you call the property accessor, which calls the AOP handler, which calls the accessor and so on), so you might need to reflect into the class containing this property to attain the backing field.