Multicast delegate and event - c#

I am studying about delegates. Few days back, I did a sample for a multicast delegates and reviewed here My previous question and clearly understood about multicast delegate.
But now I trying to do a multicast delegate sample with a event. But I got some doubts while doing sample. In the above link, I did all functions and delegate declaration in one class and add the function in to delegate using += and just call the delegate. So all function inside delegate invoked.
But now I am doing it in two different classes and trying to do all functions with the help of a event. I am providing my current code below.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
ArithmeticOperations aOperations = new ArithmeticOperations();
aOperations.StartCalculations += new ArithmeticOperations.BasicCalculations(aOperations_StartCalculations);
aOperations.PerformCalculations(20, 10);
}
void aOperations_StartCalculations(string msg)
{
MessageBox.Show(msg);
}
}
class ArithmeticOperations
{
public delegate void BasicCalculations(string msg);
public event BasicCalculations StartCalculations;
public void PerformCalculations(int n1, int n2)
{
StartCalculations("Operation Success");
}
void Add(int num1, int num2)
{
MessageBox.Show("Performing addition.");
}
void Sub(int num1, int num2)
{
MessageBox.Show("Performing substraction.");
}
void Mul(int num1, int num2)
{
MessageBox.Show("Performing multiplication.");
}
void Div(int num1, int num2)
{
MessageBox.Show("Performing division.");
}
}
Here in the Form1 is my main class and ArithmeticOperations class is using for doing functionalities. When on this statement
aOperations.PerformCalculations(20, 10);
in the Form1, the PerformCalculation() function in the ArithmeticOperations class will execute.
But my doubt is how I register all the Add, Sub, Mul and Div function to the delegate in ArithmeticOperations class to invoke all functions by just calling the delegate object and return "Operation Success" to the event callback function in Form1 class ?

Since BasicCalculations takes a single argument of type string, it cannot be used to directly invoke your methods Add, Subtract etc.
If you want PerformCalculations to invoke each of your methods via multicast, you will need a delegate of a type equivalent to Action<int, int>, eg:
class ArithmeticOperations
{
public delegate void BasicCalculations(string msg);
public event BasicCalculations StartCalculations;
private Action<int, int> calculations;
public ArithmeticOperations()
{
this.calculations += this.Add;
this.calculations += this.Sub;
}
public void PerformCalculations(int n1, int n2)
{
this.calculations.Invoke(n1, n2);
StartCalculations("Operation Success");
}
// ...
}
If you want your individual arithmetic methods to invoke your StartCalculations event with a string, you can let them do it like this:
void Add(int num1, int num2)
{
StartCalculations("Performing addition.");
}
When raising events, you should test that there are subscribers first (to avoid a NullReferenceException). The standard pattern is to get any handler subscribed, test for null then invoke the handler. This will avoid hitting a NullReferenceException, if someone unsubscribes after a testing the event for null:
void Add(int num1, int num2)
{
var handler = this.StartCalculations;
if (handler != null)
{
handler("Performing addition.");
}
}
Since that would be a lot of code repetition for each method, you can refactor it into a separate method:
void Add(int num1, int num2)
{
this.OnStartCalculation("Performing addition.");
}
void OnStartCalculation(string message)
{
var handler = this.StartCalculations;
if (handler != null)
{
handler(message);
}
}

one of the options would be creating a private event
public delegate void BasicCalculations(string msg);
public delegate void DoMath(int na, int nb);
class ArithmeticOperations
{
public ArithmeticOperations()
{
StartMath += new DoMath(ArithmeticOperations_StartMath);
}
void ArithmeticOperations_StartMath(int na, int nb)
{
Add(na, nb);
Sub(na, nb);
Mul(na, nb);
Div(na,nb);
}
public event BasicCalculations StartCalculations;
private event DoMath StartMath;
public void PerformCalculations(int n1, int n2)
{
StartMath(n1, n2);
StartCalculations("Operation Success");
}
void Add(int num1, int num2)
{
Console.WriteLine("Performing addition.");
}
void Sub(int num1, int num2)
{
Console.WriteLine("Performing substraction.");
}
void Mul(int num1, int num2)
{
Console.WriteLine("Performing multiplication.");
}
void Div(int num1, int num2)
{
Console.WriteLine("Performing division.");
}
}

Related

Action with pre prepered parameters

I want to register some actions / delegates / Events or something like this with pre prepered parameters (no parameters on invoke).
E.g.
public Action actions;
public void Main()
{
actions += Add(12);
actions += Show("something");
actions += Calculate(2, 4);
actions?.Invoke();
}
public void Add(int k) { }
public void Show(string s) { }
public void Calculate(int k, int c) { }
Alternatively something like this:
public void Main()
{
actions += Add(12);
actions += Add(1);
actions += Add(4);
actions?.Invoke();
}
Is it possible to do that?

What happens if you put functions from two classes in one delegate?

I am preparing for an exam and I have to examine various codes. One is about delegates in C# - I'm failing to see what it does, since I don't know if you can put functions from two different classes in one delegate.
Here's the code:
namespace konzolnaApplikacijaDelegateVoidMain {
public delegate int MyDelegate(int x);
class Program
{
public int number;
public Program (int x)
{
number = x;
}
public int Add(int x)
{
return x + 10;
}
public int Substract(int x)
{
return x - 10;
}
public int Multiply(int x)
{
return x * 2;
}
static void Main(string[] args)
{
MyDelegate delegate;
Program first = new Program(20);
Program second = new Program(50);
delegate = first.Add;
delegate += second.Add;
delegate -= first.Substract;
delegate += second.Multiply;
delegate += first.Add;
delegate(first.number);
delegate(second.number);
Console.Write("{0}", first.number + second.number);
}
}
}
Delegates are quite simple. Consider the following implementation of a delegate.
namespace DelegateExamples
{
class Program
{
//Declare a integer delegate to handle the functions in class A and B
public delegate int MathOps(int a, int b);
static void Main(string[] args)
{
MathOps multiply = ClassA.Multiply;
MathOps add = ClassB.Add;
int resultA = multiply(30, 30);
int resultB = add(1000, 500);
Console.WriteLine("Results: " + resultA + " " + resultB);
Console.ReadKey();
}
}
public class ClassA
{
public static int Multiply(int a, int b)
{
return a * b;
}
}
public class ClassB
{
public static int Add(int a, int b)
{
return a + b;
}
}
}

Calling delegate not reachable?

using System;
namespace _1._75_Using_a_delegate
{
public class Program
{
public delegate int Calculate(int x, int y);
public int Add(int x, int y) { return x + y; }
public int Multiply(int x, int y) { return x * y; }
public void UseDelegate()
{
Calculate calc = Add;
Console.WriteLine(calc(3, 4)); //Displays 7
calc = Multiply;
Console.WriteLine(calc(3, 4));//Displays 12
}
public static void Main()
{
//call and execute UseDelegate()
}
}
}
This should output the above results of 7 and 12.
The delegate function is not directly callable from main in the current state.
Why can't the delegate be seen from main?
Is it necessary to create a class?
How should the delegate function be called?
You cannot call the non-static method from static Method so you have to implement another class like
internal class Check
{
public delegate int Calculate(int x, int y);
public int Add(int x, int y)
{
return x + y;
}
public int Multiply(int x, int y)
{
return x * y;
}
public void UseDelegate()
{
Calculate calc = Add;
Console.WriteLine(calc(3, 4)); //Displays 7
calc = Multiply;
Console.WriteLine(calc(3, 4));//Displays 12
}
}
your call it from your Main Method like
private static void Main(string[] args)
{
new Check().UseDelegate();
}
You don't call the method at all, and you can't now since the Main method is static and your methods are not.
I would recommend to split your code off to a second class, which is easier to call. (Instead of making all methods static)
public class Assignment
{ /* all code except the Main method goes here */ }
Then, in your Main method, instantiate an instance of the Assignment class and call UseDelegate:
public static void Main()
{
Assignment a = new Assignment();
a.UseDelegate();
Console.ReadKey(); // to prevent the console from closing immediate
}

Result is not getting while multicasting

I am using a delegate type to call multiple functions from a single point. But when I do like that , I am getting the result somewhat wrong.
public delegate int MyDel(int a,int b);
public static int Add(int a, int b) { return a+b; }
public static int Sub(int a, int b) { return a-b; }
public static void Meth_del()
{
int x,y;
MyDel _delegate;
_delegate = Add;
_delegate += Sub;
Console.WriteLine( _delegate(5,4));
}
Here I should get result 9 and then 1 but only 1 is printed. How ?
This is called Closure. This happens because on the call it will execute both of the subscribed methods and you will be shown with end result.
To avoid such behavior you can unsubscribe (_delegate = null), override subscribers (=) or subscribe (+=) after first call is made.
public static void Meth_del()
{
int x,y;
MyDel _delegate;
_delegate = Add;
// Prints out 9.
Console.WriteLine( _delegate(5,4));
// Override subscribtion.
_delegate = Sub;
// Prints out 1.
Console.WriteLine( _delegate(5,4));
}
Also you can use += to add subscribers to the delegate (as you have written in your question).
Even if both methods are called only the the last method in the delegate will return the result.
Furthermore, you have only one call of Console.WriteLine(), a function cannot receive multiple return values.
To achieve what you want you might have to queue your results like this.
public static Queue<int> Results = new Queue<int>();
public static void Add(int a, int b) { Results.Enqueue(a + b); }
public static void Sub(int a, int b) { Results.Enqueue(a - b); }
public delegate void MyDel(int a, int b);
public static void Meth_del()
{
int x, y;
MyDel _delegate;
_delegate = Add;
_delegate += Sub;
_delegate(5, 4);
while (Results.Any())
Console.WriteLine(Results.Dequeue());
}
Your code does execute both methods but it only displays the return value of the last added method. If you change your methods like this:
public static int Add(int a, int b) {
Console.WriteLine(a+b);
return a+b;
}
public static int Sub(int a, int b) {
Console.WriteLine(a-b);
return a-b;
}
you will see that 9 as well as 1 are written in the console.
Yes its quite obvious that the last method in the delegate will returns the result.
public static void Meth_del()
{
int x,y;
MyDel _delegate;
_delegate = Add;
Console.WriteLine( _delegate(5,4));
_delegate += Sub;
Console.WriteLine( _delegate(5,4));
}

What is the correct syntax for calling an overloaded method using 'this()' in C#?

I may have this wrong, but I've seen the way of creating an overloaded method that calls itself in the definition. It's something like:
public void myFunction(int a, int b)
{
//Some code here
}
public void myFunction(int a) : this (a, 10)
{ }
This is not the correct syntax, I know, but I can't find the correct syntax anywhere for some reason. What is the correct syntax for this?
You are confusing constructor syntax for method syntax. The only way to do that for a method is the obvious:
public void myFunction(int a, int b)
{
//Some code here
}
public void myFunction(int a)
{
myFunction(a, 10) ;
}
although as of C#4, you can use a optional parameters:
public void myFunction(int a, int b = 10)
{
//Some code here
}
What you wrote is close to right for constructors:
public class myClass
{
public myClass(int a, int b)
{
//Some code here
}
public myClass(int a) : this (a, 10)
{ }
}
Just do this:
public void myFunction(int a, int b)
{
//Some code here
}
public void myFunction(int a)
{
myFunction(a, 10)
}
You're confusing overloading with overriding. You can call a base constructor from an derived class like this:
public MyConstructor(int foo)
:base (10)
{}
public class BaseClass {
public virtual void SomeFunction(int a, int b) {}
}
public class Derived : BaseClass {
public override SomeFunction(int a, int b) {
base.SomeFunction(a, b * 10);
}
}

Categories