please help me understand this delegate example - c#

I am trying to grasp the concept of delegate and I grabbed the following code from a SO post.
What I am not understanding is what is happening inside of Main method. I can tell from a surfacial look at it there is a new delegate object and methods with matching arguments and return types are being called by referencing the delegate object. I want to know what these three lines are doing specifically:
Valid v1 = new Valid(Test.checkInt);
v1 += new Valid(Test.checkMax);
v1 += new Valid(Test.checkMin);
Here is the actual code:
using System;
public delegate void Valid(int a);
public class Test {
public const int MAX_VALUE = 255;
public const int MIN_VALUE = 10;
public static void checkInt(int a) {
Console.Write("checkInt result of {0}: ", a);
if (a < MAX_VALUE && a > MIN_VALUE)
Console.WriteLine("max and min value is valid");
else
Console.WriteLine("max and min value is not valid");
}
public static void checkMax(int a) {
Console.Write("checkMax result of {0}: ", a);
if (a < MAX_VALUE)
Console.WriteLine("max value is valid");
else
Console.WriteLine("max value is not valid");
}
public static void checkMin(int a) {
Console.Write("checkMin result of {0}: ", a);
if (a > MIN_VALUE)
Console.WriteLine("min value is valid");
else
Console.WriteLine("min value is not valid");
Console.WriteLine("");
}
}
public class Driver {
public static void Main(string [] args) {
Valid v1 = new Valid(Test.checkInt);
v1 += new Valid(Test.checkMax);
v1 += new Valid(Test.checkMin);
v1(1);
v1(10);
v1(20);
v1(30);
v1(254);
v1(255);
v1(256);
Console.ReadLine();
}
}

Valid v1 = new Valid(Test.checkInt);
v1 += new Valid(Test.checkMax);
v1 += new Valid(Test.checkMin);
That code sets up a Multi-Cast Delegate. It means that, when you execute v1 with a parameter (which is what's happening in the Main method), it will pass that parameter to all three check methods and execute them in sequence. The method parameter is specified in the delegate declaration.

Valid v1 = new Valid(Test.checkInt);
v1 += new Valid(Test.checkMax);
v1 += new Valid(Test.checkMin);
The first line declares a new delegate v1 (analogous to a function pointer). For now, its pointing to Test.checkInt.
Then with the += operator you make the delegate point to a second method, promoting it to a MulticastDelegate. The same thing happens on the third line.
On the following lines you invoke the delegate, which in turn invokes all methods that it is pointing to. The parameters passed to the delegate, will be passed to each of these methods.

The three lines in question define delegates conforming to the signature of Valid, using methods with the corresponding return type and parameters. The += operator makes a so-called multicast delegate from regular delegates. When a multicast delegate is called, its implementation calls the component delegates, producing the effects that you see.

The += operator for delegates is a way to combine delegates. It will create a new delegate that, when called, will invoke all of the methods that the delegate would have invoked before, in addition to this new method.
In this case, after executing those lines of code, invoking v1 will execute Test.checkInt, Test.checkMax, and Test.checkMin.

Related

Using a method call as an argument for an established method

Here is the direct text from working in Unity/C# book:
try creating a new method that takes in an int parameter and simply
prints it out to the console. No return type necessary. When you've
got that, call the method in Start, pass in a GenerateCharacter method
call as its argument, and take a look at the output.
I've tried a few different things (declaring variable in Start, creating new method and calling it, with Debug.Log in the body), but no luck. Not sure where to start.
public class LearningCurve : MonoBehaviour
{
void Start()
{
int characterLevel = 32;
int nextSkillLevel = GenerateCharacter("Spike", characterLevel);
Debug.Log(nextSkillLevel);
Debug.Log(GenerateCharacter("Faye", characterLevel));
}
public int GenerateCharacter(string name, int level)
{
//Debug.LogFormat("Character: {0} - Level: {1}", name, level);
return level + 5;
}
}
Start at the Action and Function types in C#
Action Delegate - Use it when you don't need any return type
Function Delegate - Use it when you need a return type
(Hint) You can do this:
int characterLevel = 1;
Func<string,int,int> functionStoringVariable = GenerateCharacter;
// Call the function by the variable
int result = functionStoringVariable("Spike", characterLevel);

Is multicast delegate create new reference for each chaining?

Is multicast delegate create new reference for each chaining? or its a value type (MSDN says otherwise)? I don't understand, please take look at the following code.
using System;
class TestClass
{
static void Main()
{
Action origin = new Action(() => { Console.WriteLine("1st line"); });
Action copyFromOrigin;
copyFromOrigin = origin;
origin += new Action(() => { Console.WriteLine("2nd line"); });
copyFromOrigin.Invoke();
//result is "1st line", why the "2nd line" is missing?
//shouldn't the copyFromOrigin is referencing the origin?
Console.ReadKey();
}
}
Delegates are immutable....
When you add a new handler a new delegate is created.
Under the hood it calls the Delegate.Combine Method
Concatenates the invocation lists of two delegates.
Returns
A new delegate with an invocation list that concatenates the
invocation lists of a and b in that order. Returns a if b is null,
returns b if a is a null reference, and returns a null reference if
both a and b are null references.
You can see it in action here
Action action = <>c.<>9__0_0 ?? (<>c.<>9__0_0 = new Action(<>c.<>9.<M>b__0_0));
Action action2 = action;
action = (Action)Delegate.Combine(action, <>c.<>9__0_1 ?? (<>c.<>9__0_1 = new Action(<>c.<>9.<M>b__0_1)));
action2();
Console.ReadKey();
Because it's immutable type and each assignment creates new instance copied from original one. Note it's still reference type but just of special kind.

std::bind equivalent in C# or VB.NET

I am in the process of refactoring "synchronous" code (i.e. uses Windows events to wait until some other thread finished doing something) to "asynchronous" code (using delegates to implement a callback mechanism).
In the sync code, I sometimes have local variables that I need to use after the wait is over. When code like that goes async, those local variables are lost (the callback handler can't access them). I can store them as class attributes, but it feels wasteful.
In C++, I use std::bind to work around this. I just add as many parameters as local variables needed to the callback handler, and bind them when I call the async method. For example, let's say that the async method callback receives an object of type CallbackParam and the caller uses two local variables of type LocalA and LocalB.
void AsyncClass::MethodWhichCallsAsyncMethod(){
LocalA localVarA;
LocalB localVarB;
// OnAsyncMethodDone will need localVarA and localVarB, so we bind them
AsyncMethod( std::bind( &AsyncClass::OnAsyncMethodDone, this, std::placeholders::_1, localVarA, localVarB ) );
}
void AsynClass::AsyncMethod( std::function<void(CallbackParam)> callback ){
CallbackParam result;
//Compute result...
if( callback )
callback( result );
}
void AsyncClass::OnAsyncMethodDone( CallbackParam p, LocalA a, LocalB b ){
//Do whatever needs to be done
}
Is there some sort of equivalent to this in C# and VB.NET? Using delegates or something else?
UPDATE: For completeness' sake, here is the C# equivalent of my example based on #lasseespeholt's answer:
using System;
public class AsyncClass {
public void MethodWhichCallsAsyncMethod() {
var a = new LocalA();
var b = new LocalB();
//Anonymous callback handler (equivalent to AsyncClass::OnAsyncMethodDone)
Action<CallbackParam> callback = result => {
//Do what needs to be done; result, a and b can be accessed
};
AsyncMethod( callback );
}
private void AsyncMethod( Action<CallbackParam> callback ) {
var result = new CallbackParam();
//Compute result...
if( callback != null )
callback( result );
}
}
UPDATE: This should almost certainly not be used. Use the async/await keywords in C#
You can exploit closures like the following:
void MethodWhichCallsAsyncMethod()
{
int foo = 1;
AsyncCallback callback = result =>
{
Console.WriteLine(foo); // Access to foo
};
AsyncMethod(callback);
}
void AsyncMethod(AsyncCallback callback)
{
IAsyncResult result = null; // Compute result
callback(result);
}
The compiler generates a class which contains "foo" so you don't save anything with this approach, but it's clean.

what does callback mean? [duplicate]

What's a callback and how is it implemented in C#?
I just met you,
And this is crazy,
But here's my number (delegate),
So if something happens (event),
Call me, maybe (callback)?
In computer programming, a callback is executable code that is passed as an argument to other code.
—Wikipedia: Callback (computer science)
C# has delegates for that purpose. They are heavily used with events, as an event can automatically invoke a number of attached delegates (event handlers).
A callback is a function that will be called when a process is done executing a specific task.
The usage of a callback is usually in asynchronous logic.
To create a callback in C#, you need to store a function address inside a variable. This is achieved using a delegate or the new lambda semantic Func or Action.
public delegate void WorkCompletedCallBack(string result);
public void DoWork(WorkCompletedCallBack callback)
{
callback("Hello world");
}
public void Test()
{
WorkCompletedCallBack callback = TestCallBack; // Notice that I am referencing a method without its parameter
DoWork(callback);
}
public void TestCallBack(string result)
{
Console.WriteLine(result);
}
In today C#, this could be done using lambda like:
public void DoWork(Action<string> callback)
{
callback("Hello world");
}
public void Test()
{
DoWork((result) => Console.WriteLine(result));
DoWork(Console.WriteLine); // This also works
}
Definition
A callback is executable code that
is passed as an argument to other code.
Implementation
// Parent can Read
public class Parent
{
public string Read(){ /*reads here*/ };
}
// Child need Info
public class Child
{
private string information;
// declare a Delegate
delegate string GetInfo();
// use an instance of the declared Delegate
public GetInfo GetMeInformation;
public void ObtainInfo()
{
// Child will use the Parent capabilities via the Delegate
information = GetMeInformation();
}
}
Usage
Parent Peter = new Parent();
Child Johny = new Child();
// Tell Johny from where to obtain info
Johny.GetMeInformation = Peter.Read;
Johny.ObtainInfo(); // here Johny 'asks' Peter to read
Links
more details for C#.
A callback is a function pointer that you pass in to another function. The function you are calling will 'callback' (execute) the other function when it has completed.
Check out this link.
If you referring to ASP.Net callbacks:
In the default model for ASP.NET Web
pages, the user interacts with a page
and clicks a button or performs some
other action that results in a
postback. The page and its controls
are re-created, the page code runs on
the server, and a new version of the
page is rendered to the browser.
However, in some situations, it is
useful to run server code from the
client without performing a postback.
If the client script in the page is
maintaining some state information
(for example, local variable values),
posting the page and getting a new
copy of it destroys that state.
Additionally, page postbacks introduce
processing overhead that can decrease
performance and force the user to wait
for the page to be processed and
re-created.
To avoid losing client state and not
incur the processing overhead of a
server roundtrip, you can code an
ASP.NET Web page so that it can
perform client callbacks. In a client
callback, a client-script function
sends a request to an ASP.NET Web
page. The Web page runs a modified
version of its normal life cycle. The
page is initiated and its controls and
other members are created, and then a
specially marked method is invoked.
The method performs the processing
that you have coded and then returns a
value to the browser that can be read
by another client script function.
Throughout this process, the page is
live in the browser.
Source: http://msdn.microsoft.com/en-us/library/ms178208.aspx
If you are referring to callbacks in code:
Callbacks are often delegates to methods that are called when the specific operation has completed or performs a sub-action. You'll often find them in asynchronous operations. It is a programming principle that you can find in almost every coding language.
More info here: http://msdn.microsoft.com/en-us/library/ms173172.aspx
Dedication to LightStriker:
Sample Code:
class CallBackExample
{
public delegate void MyNumber();
public static void CallMeBack()
{
Console.WriteLine("He/She is calling you. Pick your phone!:)");
Console.Read();
}
public static void MetYourCrush(MyNumber number)
{
int j;
Console.WriteLine("is she/he interested 0/1?:");
var i = Console.ReadLine();
if (int.TryParse(i, out j))
{
var interested = (j == 0) ? false : true;
if (interested)//event
{
//call his/her number
number();
}
else
{
Console.WriteLine("Nothing happened! :(");
Console.Read();
}
}
}
static void Main(string[] args)
{
MyNumber number = Program.CallMeBack;
Console.WriteLine("You have just met your crush and given your number");
MetYourCrush(number);
Console.Read();
Console.Read();
}
}
Code Explanation:
I created the code to implement the funny explanation provided by LightStriker in the above one of the replies. We are passing delegate (number) to a method (MetYourCrush). If the Interested (event) occurs in the method (MetYourCrush) then it will call the delegate (number) which was holding the reference of CallMeBack method. So, the CallMeBack method will be called. Basically, we are passing delegate to call the callback method.
Please let me know if you have any questions.
Probably not the dictionary definition, but a callback usually refers to a function, which is external to a particular object, being stored and then called upon a specific event.
An example might be when a UI button is created, it stores a reference to a function which performs an action. The action is handled by a different part of the code but when the button is pressed, the callback is called and this invokes the action to perform.
C#, rather than use the term 'callback' uses 'events' and 'delegates' and you can find out more about delegates here.
callback work steps:
1) we have to implement ICallbackEventHandler Interface
2) Register the client script :
String cbReference = Page.ClientScript.GetCallbackEventReference(this, "arg", "ReceiveServerData", "context");
String callbackScript = "function UseCallBack(arg, context)" + "{ " + cbReference + ";}";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "UseCallBack", callbackScript, true);
1) from UI call Onclient click call javascript function for EX:- builpopup(p1,p2,p3...)
var finalfield= p1,p2,p3;
UseCallBack(finalfield, ""); data from the client passed to server side by using UseCallBack
2) public void RaiseCallbackEvent(string eventArgument) In eventArgument we get the passed data
//do some server side operation and passed to "callbackResult"
3) GetCallbackResult() // using this method data will be passed to client(ReceiveServerData() function) side
callbackResult
4) Get the data at client side:
ReceiveServerData(text) , in text server response , we wil get.
A callback is a function passed as an argument to another function. This technique allows a function to invoke the parameter function argument and even to pass a value back to the caller. A callback function can be designed to run before/after the function has finished and can pass a value.
It is a kind of construct where you call a long running function and ask him to call you back once it has finished with can return a parameter result to the caller.
It's like someone calls you in the middle of your work asking for status and you say "you know what give me 5 min and i will call you back" and at the end you call him to update. If you are a function the caller just added and passed another function that you invoked at the end. This can simpley be written in C# as:
public void VinodSrivastav(Action statusUpdate){
//i am still here working..working
//i have finished, calling you
statusUpdate();
}
//invokes
stackoverflow.VinodSrivastav((cam) => {
Console.Write("Is it finished");
});
The one simple example is the iterator function where the return will be multiple times, one can argue that we have yield for it:
public void IntreationLoop(int min, int max,Action<int> Callback)
{
for(int i = min;i<= max;i++)
Callback(i);
}
//call
IntreationLoop(5,50,(x) => { Console.Write(x); }); //will print 5-50 numbers
In the code above the function return type is void but it has an Action<int> callback which is called and sends each item from the loop to the caller.
The same thing can be done with if..else or try..catch block as:
public void TryCatch(Action tryFor,Action catchIt)
{
try{
tryFor();
}
catch(Exception ex)
{
Console.WriteLine($"[{ex.HResult}] {ex.Message}");
catchIt();
}
}
And call it as:
TryCatch(()=>{
int r = 44;
Console.WriteLine("Throwing Exception");
throw new Exception("something is wrong here");
}, ()=>{
Console.WriteLine("It was a mistake, will not try again");
});
In 2022 we have Func & Action doing the same, please see the demo code below which shows how this can be be used:
void Main()
{
var demo = new CallbackDemo();
demo.DoWork(()=> { Console.WriteLine("I have finished the work"); });
demo.DoWork((r)=> { Console.WriteLine($"I have finished the work here is the result {r}"); });
demo.DoWork(()=> { Console.WriteLine($"This is passed with func"); return 5;});
demo.DoWork((f)=> { Console.WriteLine($"This is passed with func and result is {f}"); return 10;});
}
// Define other methods and classes here
public class CallbackDemo
{
public void DoWork(Action actionNoParameter)
{
int a = 5;
int b = 10;
//i will do th maths and call you back
int result = a + b;
//callback
actionNoParameter(); //execute
Console.WriteLine($"[The Actual Result is {result}]");
}
public void DoWork(Action<int> actionWithParameter)
{
int a = 5;
int b = 10;
//i will do th maths and call you back
int result = a + b;
//callback
actionWithParameter(result); //execute
Console.WriteLine($"[The Actual Result is {result}]");
}
public void DoWork(Func<int> funcWithReturn)
{
int a = 5;
int b = 10;
//i will do th maths and call you back
int result = a + b;
//callback
int c = funcWithReturn(); //execute
result += c;
Console.WriteLine($"[The Actual Result is {result}]");
}
public void DoWork(Func<int,int> funcWithParameter)
{
int a = 5;
int b = 10;
//i will do th maths and call you back
int result = a + b;
//callback
result += funcWithParameter(result); //execute
Console.WriteLine($"[The Actual Result is {result}]");
}
}

Java vs C# - AddActionListener vs event subscription

Very simple question from one somewhat new to Java: when adding an event handler (or whatever it is called in Java) to a Control, MUST it be an object? I mean, in C# I can do
control.event += System.eventHandler(methodThatHandlesEvent)
Sure, that's because we have delegate types in C#, but I was wondering if I can choose which method would be called when an event is raised in Java? I mean, in Java I can have something like:
control.AddActionListener(objectWhichClassImplementsActionListener)
And then I have the actionPerformed method in this class, which is the only method that is called. I know there are more kinds of listeners, but I can't have a "ActionListenerHandler" class in which I implement several actionPerformed methods that can be assigned to different controls?
Java has no "method pointers", or function types or something like that, so you have to use the ActionListener interface with its actionPerformed method, yes. In most cases I give an object of an anonymous class there, which only calls the method which is handling it:
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
myRealMethod();
}
});
This is a bit verbose compared to the C# version, but Java has never been a language to save code lines.
If you want to have it a bit shorter, you can use reflection to help.
package de.fencing_game.paul.examples;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import javax.swing.*;
/**
* An adapter class for calling an (almost) arbitrary
* method as an ActionListener.
*<p>
* In fact, you can use any public method which has either no parameter
* or any parameter of type {#link ActionEvent} or some superclass
* of it (then it gets passed the ActionEvent there).
*</p>
* <p>
* Additionally, the adapter needs an object of a class containing
* this method as the receiver.
* </p>
*<p>
* Inspired by the question Java vs C# - AddActionListener vs event subscription on Stackoverflow.
*</p>
* #author Paŭlo Ebermann
*/
public class MethodAdapter implements ActionListener {
/** the receiver object. */
private Object target;
/** the method to be invoked. */
private Method method;
/** true if the method accepts the ActionEvent argument,
false if it is a no-arg method. */
private boolean takesArgument;
/**
* creates a new MethodAdapter.
* #param o the receiver object.
* #param mName the name of a method on the receiver.
* If there are multiple same-named methods in the class
* of the receiver, we take the first one of these: <ul>
* <li> a public method taking an ActionEvent as parameter</li>
* <li> a public method taking an AWTEvent as parameter</li>
* <li> a public method taking an EventObject as parameter</li>
* <li> a public method taking an Object as parameter</li>
* <li> a public method taking no parameter.</li>
* </ul>
* #throws IllegalArgumentException if there is no such method.
*/
public MethodAdapter(Object o, String mName) {
this(o, findMethod(o, mName));
}
/**
* creates a new MethodAdapter.
* #param o the receiver object.
* #param m the method to be invoked.
* This method has to be declared in the class of the receiver object
* or some supertype, has to take no or one argument, and if one, then
* of some supertype of {#link ActionEvent}.
* #throws IllegalArgumentException if the method does not fit the
* receiver, if the method takes too much arguments or arguments of
* wrong types.
*/
public MethodAdapter(Object o, Method m) {
Class<?>[] params = m.getParameterTypes();
if(!m.getDeclaringClass().isInstance(o)) {
throw new IllegalArgumentException("wrong target object");
}
if(params.length > 1) {
throw new IllegalArgumentException("too many arguments");
}
if(params.length == 1 &&
! params[0].isAssignableFrom(ActionEvent.class)) {
throw new IllegalArgumentException("method not compatible: " + m);
}
this.target = o;
this.method = m;
this.takesArgument = params.length > 0;
}
private static Method findMethod(Object o, String mName) {
Class<?> c = o.getClass();
Class<?> eventClass = ActionEvent.class;
while(eventClass != null) {
try {
return c.getMethod(mName, ActionEvent.class);
}
catch(NoSuchMethodException ex) {}
eventClass = eventClass.getSuperclass();
}
try {
// try a no-argument method
return c.getMethod(mName);
}
catch(NoSuchMethodException ex) {
throw new IllegalArgumentException("No fitting method named '" +
mName +"' on this object " + o +
" of class " + c.getName());
}
}
/**
* the implementation of the actionPerformed method.
* We delegate to our target object and method.
* Any return value of
* the method is silently ignored.
* #throws RuntimeException if any exception is thrown by the invoked
* method (or during the invoke process), it is wrapped in a
* RuntimeException and rethrown.
*/
public void actionPerformed(ActionEvent event) {
try {
if(takesArgument) {
method.invoke(target, event);
}
else {
method.invoke(target);
}
}
catch(Exception e) {
if(e instanceof InvocationTargetException) {
Throwable t = e.getCause();
if(t instanceof Error)
throw (Error)t;
e = (Exception)t;
}
if(e instanceof RuntimeException)
throw (RuntimeException) e;
throw new RuntimeException(e);
}
}
/**
* main method for testing purposes.
*/
public static void main(String[] params) {
JFrame f = new JFrame("Test");
JButton b = new JButton("close");
b.addActionListener(new MethodAdapter(f, "dispose"));
f.getContentPane().add(b);
f.setVisible(true);
}
}
Having this class, you can write
button.addActionListener(new MethodAdapter(this, "myRealMethod"));
instead of the above code, and on the button click the method will be called.
Note that now the compiler can't do any type checks, so it has to be done on runtime (and you should check your System.err for exceptions stack traces - the application will continue to run even if some event listener throws exceptions). It will be a bit slower, too, but for user interaction this should not really matter.
This is now also part of my github repository.
Update: With Java 8, there are method reference expressions (like this::myRealMethod). Java still doesn't have function types, so those expressions are only possible where a SAM-interface (single abstract method) is needed, and then are wrapped into a compiler-generated implementation of that interface, which includes the target object reference and an implementation of the interface's method which calls the target method.
MUST it be an object?
In Java all should be an Object)
You can declare your listeners as you want with any number of methods with any number of parameters, but Observable object should know what method call and what arguments pass.
You can use an anonymous inner class to avoid having the ActionListener declared separately and cluttering up your project with unnecessary helper classes:
control.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Button clicked.");
}
});
Note the new ActionListener() { ... }, which is declaring an anonymous class which implements ActionListener.
Make a class that will encapsulate sub-classes like
public class MyEvents
{
public class MyEvent_1 : ActionListner
{
....
}
public class MyEvent_2 : ActionListner
{
....
}
}
this way all your event will be at the same place as you want.

Categories

Resources