So I was wondering if something like this is possible:
I am a program, I am about to create an instance of one of my objects. I fire an event letting any subscribers know that I am about to create an object. As a part of this event I pass through a Hashtable that I will later pass to the constructor of my object.
Subscribers would then be able to modify this Hashtable yes? They could add entries for a delegate type with a delegate of that type as the value? Once the subscriber finishes doing their business, the pre-create event finishes. Would the changes made to the Hashtable be represented in the object that fired the event? So then if this Hashtable was passed to the constructor of an object, that object could potentially contain methods from an outside source?
So essentially -
Go to create object
Fire request delegate event
Use delegate hashtable modified by event in constructor of object
Object uses methods from hashtable in place of own if exists delegate of same type
Now object runs custom code on standard functions
Again, I really don't know if what I'm saying is even possible, or makes sense.
It's possible, but I would recommend against sending a HashSet<T> openly. The reason being that any subscriber could modify the values in the HashSet<T>.
Instead, I don't know that an event is the right course of action here. I would still use delegates, but I would not expose them as events. A pub/sub pattern might be better here (where an object that wants to be notified would pass the delegate through Sub/Unsub methods).
This allows you to modify the delegate signature so that the implementation will return the data values to you when you make the call (instead of passing around the HashSet<T>).
Then, instead of just making one call, you would call GetInvocationList to get each individual delegate. You would then loop through and collect the values that are returned.
From that point, you would aggregate the values appropriately and then pass that aggregate to the constructor of your objects.
Related
I've just learned about how delegates are implemented from the book CLR via C#:
A delegate object has two parts: closure (target + function pointer), and
invocation list. One object uses only one of them.
Combining non-null delegates using Delegate.Combine always create a new delegate object with a new invocation list that contains all combined delegates.
Delegate.Remove create two objects as well when there are still multiple delegates to call.
Delegate.Combine and Delegate.Remove are default implementation for event DelegateType.
I have some questions on it:
Is this behaviour common for .net runtime? Is there a different implementation?
Invocation list seems to be an array. It's copied everywhere. Why not simply modify array elements, list List<T>?
It seems that using HashSet<DelegateType> instead of event DelegateType gets much better performance: reducing add/remove complexity and GC pressure. What's the cost?
I was reading a book illustrated C # 2012 in the section Combining Delegates point not notice that? Purpose of the delegates are immutable.
Combining Delegates
All the delegates you’ve seen so far have had only
a single method in their invocation lists. Delegates can be “combined”
by using the addition operator. The result of the operation is the
creation of a new delegate, with an invocation list that is the
concatenation of copies of the invocation lists of the two operand
delegates. For example, the following code creates three delegates.
The third delegate is created from the combination of the first two.
MyDel delA = myInstObj.MyM1;
MyDel delB = SClass.OtherM2;
MyDel delC = delA + delB; // Has combined invocation list
Although the term combining delegates might give the impression that
the operand delegates are modified, they are not changed at all. In
fact, delegates are immutable. After a delegate object is created, it
cannot be changed. Figure 15-6 illustrates the results of the
preceding code. Notice that the operand delegates remain unchanged.
Thread-safety and speed are the primary concerns here. A delegate update is not atomic, it requires updating 6 fields and a list. Making it atomic so it cannot get corrupted requires a lock, far too expensive for such a basic operation that rarely needs to be thread-safe.
By making it immutable, the delegate object cannot get corrupted since it always sets fields on an object that nobody has a reference to yet. Reassigning the delegate object reference is atomic, a basic .NET memory model guarantee. So no need for a lock anymore. The trade-off is less efficient memory use, it is a small penalty.
Do keep in mind that the thread-safe delegate update does not automatically make your code thread-safe as well. The test-and-fire code needs to copy the reference to avoid NRE and you can make a callback to a method that was already unsubscribed.
Delegates are pointers to a method, either concrete or anonymous (well, even anonymous methods are compiled with some compiler-generated identifier).
Would be reasonable that something that points to some concrete thing be mutable? I don't think so. Each instance represents a pointer to some method. Do you want to point to some other method? Create a new pointer. That is, you instantiate a new delegate.
In the other hand, the addition of two or more delegates has this result because + operator can be overloaded. That is, delegates can be part of an addition but internally +'s overload is creating a new delegate with an invocation list.
I am a beginner in C# events , and delegates. Few questions that would make sense if you look at the URL I have used to learn about events.
Can I ever have an event without a delegate associated to it? The exmaples that I have found always have them together.
For example I do not understand how does the event get generated. I am totally lost, I understand that Tick is defined as an event but what is the Tick's event description? where do I define what constitutes the Tick?
Also where does the Tick value gets ever initailized. It seems that all the examples I have looked at never initialize the event and have a similar statement to statement : If (Tick ! =null) in the attached example but it is not obviuos where is the Tick is initialized. I have looked around and I just cant find any answer.
Thanks in advance for your help
No, events are just a special use of delegates. You can't have an event without a delegate (though you can have a delegate without an event - read up on delegates for more info).
Not really sure I understand your question here. The description of the event would be in the documentation. Looking at the code alone, you just know that there is an event called Tick on that object that you can attach an event handler to.
When you add an event handler to Tick (that's the += lines you see) it will become non-null. That's what those != null checks are doing - making sure that someone has attached onto the event.
An event is simply a combination of an add method and a remove method, both of which take a single parameter of the same delegate type. What the event does with a passed-in delegate is entirely up to the implementation.
The most common thing to do with an event delegate received in the Add handler is to Delegate.Combine it with the previously-added delegates (if any), but there are some other possibilities as well:
If an object will support many kinds of events, but many instances will have zero subscribers for most of them, one could add the delegate to a table. Many WinForms events do this.
If one wants to allow subscribers to use contravariant delegate types, one could place received delegates into an array, List<>, linked list, of delegates or delegate-holding objects.
If the event represents something that some types of objects would fire, but a particular instance never will, the event may simply discard the delegate. Consider, for example, an abstract ObservableFoo class with an abstract change-notification event, and a contract that says any time the instance's properties change it will invoke all passed-in delegates will be invoked; an ImmutableFoo class derived from it could accept subscription requests, but since it would never change, it would never have to invoke the passed-in delegates (or do anything else with them) and could simply discard them.
Since an event is a pair of methods which take a delegate type as a parameter, every event must "by definition" use delegates as its parameter type. All non-trivial events must store passed-in delegates in some form. The most common way to accept multiple subscriptions is to combine them into a multicast delegate (I dislike the design, btw, but it is the most common); other approaches may be employed, but an event which is going to use passed-in delegates must store them somehow.
BTW, there are two ways to declare an event in C#: one may supply the add/remove handlers explicitly, in which case the compiler will create a event with those handlers. One may also supply just the event name and delegate type, in which case the compiler will create an event with the specified name and scope, a private variable with the same name and appropriate delegate type, and thread-safe add/remove methods which add or remove the event from the indicated variable. Statements of the form eventName += something; or eventName -= something; will be processed as calls to the "add" or "remove" methods; all other uses of the name will refer to the delegate. Note that in old versions of C#, use of eventName += something; and eventName -= something; within a class would be processed using the += and -= operations on the delegate which were not thread-safe, but newer versions have changed that behavior.
I have an event delegate that is defined as follows:
public delegate void CallbackDelegate(Data data);
public event CallbackDelegate OnDataComplete;
I raise the event asynchronously:
// Raise the OnDataComplete event
OnDataComplete.BeginInvoke(new Data(), null, null);
Subsequently, the signature of BeginInvoke looks like:
IAsyncResult CallbackDelegate.BeginInvoke(Data data, AsyncCallback callback, object #object)
In most examples I've seen BeginInvoke is called with the #object parameter being null, but I can't find the documentation which explains what is the purpose of that parameter.
So what is the purpose of that parameter? What can we use it for?
You can provide anything you want there. In the AsyncResult method you can retrieve this value with IAsyncResult.AsyncState. It's there for your use.
It's so that you can pass any relevant information from your method to the callback. Since C# has lambda expressions and since delegates can have state, sometimes this is useless, and you can just pass null. But it's a bit similar to Control.Tag, and it lets you give information to the callback that it might find handy.
Update:
The origin of why it even exists goes back to languages that only had function pointers, with no closure. (You might want to look up the word "closure"... I can't explain it very concisely.) In C, there's only function pointers and not delegates; hence, function pointers can't hold state. So whenever you provided a callback, the callee helped you by passing an additional pointer for you, so you could pass data to your callback that it might need. In .NET, these are less necessary (because delegates have Target objects and can hold state), but sometimes they're handy and that's where they come from.
That's just a state object that ends up in IAsyncResult.AsyncState that can be retrieved in your AsyncCallback code. Kinda like the ThreadPool.QueueWorkItem(WaitCallback, Object).
I understand delegates encapsulate method calls. However I'm having a hard time understanding their need. Why use delegates at all, what situations are they designed for?
A delegate is basically a method pointer. A delegate let us create a reference variable, but instead of referring to an instance of a class, it refers to a method inside the class. It refers any method that has a return type and has same parameters as specified by that delegate. It's a very very useful aspect of event. For thorough reading I would suggest you to read the topic in Head First C# (by Andrew Stellman and Jennifer Greene). It beautifully explains the delegate topic as well as most concepts in .NET.
Well, some common uses:
Event handlers (very common in UI code - "When the button is clicked, I want this code to execute")
Callbacks from asynchronous calls
Providing a thread (or the threadpool) with a new task to execute
Specifying LINQ projections/conditions etc
Don't think of them as encapsulating method calls. Think of them as encapsulating some arbitrary bit of behaviour/logic with a particular signature. The "method" part is somewhat irrelevant.
Another way of thinking of a delegate type is as a single-method interface. A good example of this is the IComparer<T> interface and its dual, the Comparison<T> delegate type. They represent the same basic idea; sometimes it's easier to express this as a delegate, and other times an interface makes life easier. (You can easily write code to convert between the two, of course.)
They are designed, very broadly speaking, for when you have code that you know will need to call other code - but you do not know at compile-time what that other code might be.
As an example, think of the Windows Forms Button.Click event, which uses a delegate. The Windows Forms programmers know that you will want something to happen when that button is pressed, but they have no way of knowing exactly what you will want done... it could be anything!
So you create a method and assign it to a delegate and set it to that event, and there you are. That's the basic reasoning for delegates, though there are lots of other good uses for them that are related.
Delegates are often used for Events. According to MSDN, delegates in .NET are designed for the following:
An eventing design pattern is used.
It is desirable to encapsulate a static method.
The caller has no need access other properties, methods, or interfaces on
the object implementing the method.
Easy composition is desired.
A class may need more than one implementation of the methodimplementation of the method
Another well put explanation from MSDN,
One good example of using a
single-method interface instead of a
delegate is IComparable or
IComparable. IComparable declares the
CompareTo method, which returns an
integer specifying a less than, equal
to, or greater than relationship
between two objects of the same type.
IComparable can be used as the basis
of a sort algorithm, and while using a
delegate comparison method as the
basis of a sort algorithm would be
valid, it is not ideal. Because the
ability to compare belongs to the
class, and the comparison algorithm
doesn’t change at run-time, a
single-method interface is ideal.single-method interface is ideal.
Since .NET 2.0 it has also been used for anonymous functions.
Wikipedia has a nice explanation about the Delegation pattern,
In software engineering, the delegation pattern is a design pattern in object-oriented programming where an object, instead of performing one of its stated tasks, delegates that task to an associated helper object. It passes the buck, so to speak (technically, an Inversion of Responsibility). The helper object is called the delegate. The delegation pattern is one of the fundamental abstraction patterns that underlie other software patterns such as composition (also referred to as aggregation), mixins and aspects.
Oversimplified: I'd say that a delegate is a placeholder for a function until that time when something assigns a real function to the delegate. Calling un-assigned delegates throws an exception.
Confusion occurs because there is often little difference made between the definition, declaration, instantiation and the invocation of delegates.
Definition:
Put this in a namespace as you would any class-definition.
public delegate bool DoSomething(string withThis);
This is comparable to a class-definition in that you can now declare variables of this delegate.
Declaration:
Put this is one of function routines like you would declare any variable.
DoSomething doSth;
Instantiation and assignment:
Usually you'll do this together with the declaration.
doSth = new DoSomething(MyDoSomethingFunc);
The "new DoSomething(..)" is the instantiation. The doSth = ... is the assignment.
Note that you must have already defined a function called "MyDoSomething" that takes a string and returns a bool.
Then you can invoke the function.
Invocation:
bool result = doSth(myStringValue);
Events:
You can see where events come in:
Since a member of a class is usually a declaration based upon a definition.
Like
class MyClass {
private int MyMember;
}
An event is a declaration based upon a delegate:
public delegate bool DoSomething(string withWhat);
class MyClass {
private event DoSomething MyEvent;
}
The difference with the previous example is that events are "special":
You can call un-assigned events without throwing an exception.
You can assign multiple functions to an event. They will then all get called sequentially. If one of those calls throws an exception, the rest doesn't get to play.
They're really syntactic sugar for arrays of delegates.
The point is of course that something/someone else will do the assigning for you.
Delegates allow you to pass a reference to a method. A common example is to pass a compare method to a sort function.
If you need to decide at runtime, which method to call, then you use a delegate. The delegate will then respond to some action/event at runtime, and call the the appropriate method. It's like sending a "delegate" to a wedding you don't want to attend yourself :-)
The C people will recognize this as a function pointer, but don't get caught up in the terminology here. All the delegate does (and it is actually a type), is provide the signature of the method that will later be called to implement the appropriate logic.
The "Illustrated C#" book by Dan Solis provides the easiest entry point for learning this concept that I have come across:
http://www.amazon.com/Illustrated-2008-Windows-Net-Daniel-Solis/dp/1590599543
A delegate is typically a combination of an object reference and a pointer to one of the object's class methods (delegates may be created for static methods, in which case there is no object reference). Delegates may be invoked without regard for the type of the included object, since the included method pointer is guaranteed to be valid for the included object.
To understand some of the usefulness behind delegates, think back to the language C, and the printf "family" of functions in C. Suppose one wanted to have a general-purpose version of "printf" which could not only be used as printf, fprintf, sprintf, etc. but could send its output to a serial port, a text box, a TCP port, a cookie-frosting machine, or whatever, without having to preallocate a buffer. Clearly such a function would need to accept a function pointer for the character-output routine, but that by itself would generally be insufficient.
A typical implementation (unfortunately not standardized) will have a general-purpose gp_printf routine which accepts (in addition to the format string and output parameters) a void pointer, and a pointer to a function which accepts a character and a void pointer. The gp_printf routine will not use the passed-in void pointer for any purpose itself, but will pass it to the character-output function. That function may then cast the pointer to a FILE* (if gp_printf is being called by fprintf), or a char** (if it's being called by sprintf), or a SERIAL_PORT* (if it's being called by serial_printf), or whatever.
Note that because any type of information could be passed via the void*, there would be no limit as to what gp_printf could do. There would be a danger, however: if the information passed in the void* isn't what the function is expecting, Undefined Behavior (i.e. potentially very bad things) would likely result. It would be the responsibility of the caller to ensure that the function pointer and void* are properly paired; nothing in the system would protect against incorrect usage.
In .net, a delegate would provide the combined functionality of the function pointer and void* above, with the added bonus that the delegate's constructor would ensure that the data was of the proper type for the function. A handy feature.