Clarification about delegates - c#

What is the below code doing? I think the pointer will be changed to the multiply method.
But what is "+=" doing here. I am confused.
delegate int calc(int a , int b);
static void Main(string[] args)
{
calc c = new calc(Add);
c += new calc(Multiply);
Console.WriteLine(c(3, c(4, 2)));
Console.Read();
}
public static int Add(int a, int b)
{
return (a + b);
}
public static int Multiply(int a, int b)
{
return (a * b);
}

The + and += operator
Similar to how you use the + operator to add values, you can use the += operator to both add and assign back to the same value.
An example of these operators applied to ints:
int a = 5;
a += 7; // a is now 12
a = a + 11;
Console.WriteLine(a);
24
Combining delegates
As AVD mentioned, you use the + and += operators to combine delegates.
When you apply these operators to delegates, you aren't doing a mathematical "sum" or "sum and assign", like my example with ints. Instead you are modifying a list of methods to be called when you invoke the delegate.
From that article:
Delegates can be combined such that when you call the delegate, a whole list of methods are called - potentially with different targets
So when you add/combine delegates, you'll end up calling multiple methods.
If you change your code to:
public static int Add(int a, int b)
{
Console.WriteLine("From Add");
return (a + b);
}
public static int Multiply(int a, int b)
{
Console.WriteLine("From Multiply");
return (a * b);
}
Then you will see this output when you run the program:
From Add
From Multiply
From Add
From Multiply
24
This is because:
You combined the Add and Multiply delegates, so both get called when you call c(x, y)
Multiply is the last delegate you added to that chain of delegates
You are calling c(x, y) twice. This is similar to if you had called: Multiply(3, Multiply(4, 2))
Return values from combined delegates
That point about the last delegate you added to the chain is also mentioned in the article:
If a delegate type is declared to return a value (i.e. it's not declared with a void return type) and a combined delegate instance is called, the value returned from that call is the one returned by the last simple delegate in the list.
The last method you added to the chain was Multiply, so all other return values are thrown out, and only the return value from Multiply is used when you call c(x, y).
You can see this demonstrated in your program. 3 * 4 * 2 is 24, which is your program's output. None of your calls to Add impact the final result.

+= is like appending multiple calls to the delegate object. Since its a multicast delegates, you can append multiple destination calls to the a single delegate. To append to a delegate, you need new delegate objects. And thats whats been doing in the second line.
Its similar to,
CalcDelegate C1, C2;
C1 = new CalcDelegate(Add);
C2 = new CalcDelegate(Multiply);
C1 = C1 + C2;

Its called Combining the delegates.

You can think of delegates as a cross between value types (like int or double) and arrays of method addresses.
You know that if you write this code:
var x = 5;
var y = x + 2;
y += 3;
Then afterwards x == 5 & y == 10 even though y had an intermediate value of 7 this was "thrown away" when the final assignment occurred.
Quite clearly the final value of y isn't 3.
In your code you wrote this:
calc c = new calc(Add);
c += new calc(Multiply);
As with y, the final value of c isn't Multiply. It's really more like this:
c == { Add, Multiply }
When you then call something like c(4, 2) you are effectively calling both Add & Multiply and because the delegate returns a value you only get back the final delegate's value - in this case from Multiply - and that's what makes it appear that the "pointer" changed to the Multiply method.
You could try adding in this code before you call c:
c -= new calc(Multiply);
and this will effectively return c back to this:
c == { Add }
And this is why delegates appear to behave like arrays of method addresses.
Now if you change your Add & Multiply methods to look like this:
public static int Add(int a, int b)
{
Console.WriteLine("Add({0}, {1})", a, b);
return (a + b);
}
public static int Multiply(int a, int b)
{
Console.WriteLine("Multiply({0}, {1})", a, b);
return (a * b);
}
you can then watch the calls as they occur. Your original code runs like this:
Add(4, 2)
Multiply(4, 2)
Add(3, 8)
Multiply(3, 8)
24
I hope this helps.

Related

Call function with a parameter from another function

I have a function that repeatedly calls another function.
The second function has a bool parameter that changes the way it behaves, so when I call the first function I want to have a parameter that specifies the way the second function behaves.
void Function1(int n, bool differentBehavior = false)
{
int a = Function2(n, differentBehavior);
int b = Function2(1, differentBehavior);
int c = Function2(2, differentBehavior);
return a + b + c;
}
int Function2(int x, bool differentBehavior)
{
if (!differentBehavior) // do something
else // do something else
}
The code itself is obviously an example (in reality the second function is called over 20 times and for code readability I would love to not have to specify the second parameter every time), but I put it there to explain what I'm currently doing. Is there no better way to achieve this?
You can introduce a local function to capture the second argument like so:
int Function1(int n, bool differentBehavior = false)
{
int func(int n) => Function2(n, differentBehavior);
int a = func(n);
int b = func(1);
int c = func(2);
return a + b + c;
}
This is called "partial function application". See more here:
https://codeblog.jonskeet.uk/2012/01/30/currying-vs-partial-function-application/
While C# doesn't support true function Currying nor first-class partial function application, you can always
use a new locally scoped function (aka a local function) to wrap your Function2 with predefined arguments... which is conceptually almost the same thing as partial application, just without referential-transparency, and awkward delegate types.
Anyway, if you want to pass the outer Function1's differentBehavior argument value to Function2 then you will need to use a closure, which will capture the variable, but this will introduce slight runtime performance complications: as a closure generally means a GC heap allocation and copying function local state from the stack onto the heap and yada yada.
However, if you're only using constant parameter values - or you're okay with using different wrappers for different predefined argument values, then you can use a static local function (requires C# 8.0 or later) which prevents you from unintentionally creating a closure.
For example:
void Function1(int n, bool differentBehavior = false)
{
// Look ma, no closure!
static int PartiallyAppliedFunc2_False(int x) => Function2( x: x, differentBehavior: false );
static int PartiallyAppliedFunc2_True(int x) => Function2( x: x, differentBehavior: true );
int a = PartiallyAppliedFunc2_False(n);
int b = PartiallyAppliedFunc2_False(1);
int c = PartiallyAppliedFunc2_True(2);
return a + b + c;
}
int Function2(int x, bool differentBehavior)
{
if (!differentBehavior) // do something
else // do something else
}
One thing to look at when a lot of parameters are being passed on the stack is whether there is some higher-level state that could be represented by a member variable of the class.
Here's some code for the most basic kind of state machine. This general approach might help solve the problem you're having:
class Program
{
enum Behaviors
{
BehaviorA,
BehaviorB,
BehaviorC,
}
static Behaviors State { get; set; }
static void Main(string[] args)
{
for (State = Behaviors.BehaviorA; State <= Behaviors.BehaviorC; State++)
{
Console.WriteLine($"Function returned { Function1(0)}");
}
int Function1(int n)
{
int a = Function2(n);
int b = Function2(1);
int c = Function2(2);
return a + b + c;
}
int Function2(int x)
{
switch (State)
{
case Behaviors.BehaviorA:
return x * 10;
case Behaviors.BehaviorB:
return x * 20;
case Behaviors.BehaviorC:
return x * 30;
default:
throw new NotImplementedException();
}
}
}
}

A simple question about delegate instantiation

I am trying to read some code on the internet, but still cannot figure it out.
The code is:
private delegate string GetAString();
static void Main()
{
int x = 40;
GetAString firstStringMethod = new GetAString(x.ToString);
Console.WriteLine(firstStringMethod());
}
My question is "delegate string GetAString()" does not need parameters, but when it is instantiated, it has the x.ToString parameter.
Why? Can anyone explain this?
Thanks.
A delegate is a special type of variable that can hold a reference to a method (not the result of the method but the method itself), allowing it to be passed around and invoked in places where you perhaps don't have access to the object the method belongs to.
From the docs:
Represents a delegate, which is a data structure that refers to a static method or to a class instance and an instance method of that class.
Your code:
GetAString firstStringMethod = new GetAString(x.ToString);
Note the lack of () at the end of x.ToString. We're not calling x.ToString() here. We're creating a GetAString and passing x.ToString (which is a method that satisfies the signature required by the delegate).
This means that when we call firstStringMethod() it will call x.ToString() and proxy the result to you.
Consider another example:
public delegate int Operation(int a, int b);
We could define multiple methods:
public int Sum(int a, int b)
{
return a + b;
}
public int Multiply(int a, int b)
{
return a * b;
}
And then switch according to user input:
Operation o;
switch (Console.ReadLine())
{
case "+":
o = new Operation(Sum);
break;
case "*":
o = new Operation(Multiply);
break;
default:
Console.WriteLine("invalid operation");
return;
}
Console.WriteLine(o(4, 3));
If the user inputs "+" then the result will be 7, while inputting "*" will result in "12".
You can see from this example that we're not passing the arguments of Sum or Multiply when we instantiate o. We're simply passing the method. We then use the delegate to supply the arguments and get the result.
Example if user input is +
Example if user input is *

Function definition in case of different type of arguments?

I am writing a simple program in which I have defined a function which accepts certain type of argument , now new requirement I got has same procedures to be done which I had already in written in earlier function , but this time it should on different type of argument.I am not able to call straight way this same function for two different types of arguments. So my question is how I should modify my function to behave in such a way. I am hoping that it is possible. I would like something as ,I have function like Sum(int 1,int j) now I would like to use same function for double type arguments.
This is called overloading. What you can do is simply write two functions:
public double Sum(int 1, int j)
public double Sum(double 1, double j)
And your program will call the appropriate one based on the arguments you pass to it.
Simple with generics
T Sum<T>(T i,T j) { ... }
However, you won't be able to do i+j or anything, so it depends.
Why don't you define a method with double as parameter type and later you can call it for integer values as well.
private double Sum(double a, double b)
{
return a+b;
}
and later you can call it like:
int a = 1;
int b = 2;
int Sum = (int) Sum(a,b);
Since an integer can be passed to a double type parameter. But if your method involves complex calculation then you are better of with multiple overloads of the Sum method with different types.
In .NET there is no type encompassing different numeric types. So you need two overloads of the same method, one that takes int arguments, one that takes double arguments.
You declare a new method with the same amount of parameters but different types.
public Int32 Sum(Int32 i, Int32 j)
{
return i + j;
}
public Double Sum(Double i, Double j)
{
return i + j;
}
So you have a method that takes int parameters
public int Sum(int val1,int val2)
{
return val1 + val2;
}
Now you need a method that takes doubles:
public double Sum(double val1,double val2)
{
return val1 + val2;
}
If you want a generic class which supports all "numeric" types you can have a look here:
http://www.codeproject.com/Articles/33617/Arithmetic-in-Generic-Classes-in-C
You can write GENERIC METHODS for different datatypes.
check this Link
Look more into this link. It shows how o create a function that can handle several datatypes.
int a = 2, b = 3;
double c = 2.345, d = 3.45;
object inta = a, intb = b;
object doublec = c, doubled = d;
Console.WriteLine(Sum(inta, intb).ToString());
Console.WriteLine(Sum(doublec, doubled).ToString());
public object Sum(object a, object b)
{
object sum = null;
if (a.GetType().ToString() == "System.Int32" && b.GetType().ToString() == "System.Int32")
{
sum = Convert.ToInt32(a.ToString()) + Convert.ToInt32(b.ToString());
}
if (a.GetType().ToString() == "System.Double" && b.GetType().ToString() == "System.Double")
{
sum = Convert.ToDouble(a.ToString()) + Convert.ToDouble(b.ToString());
}
return sum;
}

Func delegate doesn't chain methods

Lets imagine simple delegate calls:
void Main()
{
Func<int, int, string> tfunc = null;
tfunc += Add; // bind first method
tfunc += Sub; // bind second method
Console.WriteLine(tfunc(2, 2));
}
private string Add(int a, int b)
{
return "Add: " + (a + b).ToString();
}
private string Sub(int a, int b)
{
return "Sub: " + (a - b).ToString();
}
The result of this program is:
Sub: 0
So, why Add method was not called? I'm expecting to call Method Add, and then method Sub.
Add was correctly chained and called, take a look at the result of
void Main()
{
Func<int, int, string> tfunc = null;
tfunc += Add; // bind first method
tfunc += Sub; // bind second method
Console.WriteLine(tfunc(2, 2));
}
private string Add(int a, int b)
{
Console.WriteLine("Inside Add");
return "Add: " + (a + b).ToString();
}
private string Sub(int a, int b)
{
Console.WriteLine("Inside Sub");
return "Sub: " + (a - b).ToString();
}
It is:
Inside Add
Inside Sub
Sub: 0
What is not chained, because there is no way to access it, is the result of the Add method. Delegates that return a value, in case of chaining, return the value of the last method invoked, that is the last method that was added to the delegate.
This is specified in part 15.4 of the C# 4.0 language specification
Invocation of a delegate instance whose invocation list contains
multiple entries proceeds by invoking each of the methods in the
invocation list, synchronously, in order. ...
If the delegate invocation includes output parameters or a
return value, their final value will come from the invocation of the
last delegate in the list.
The problem is that the return value is not passed between the method invocations, so the output only captures the last string returned. I.e. the return of Add is lost.

Generic Factorial function in C#

I want to write a generic function to calculate factorial in C# ... like:
static T Factorial<T>(T n)
{
if (n <= 1)
return 1;
return Factorial<T>(n - 1);
}
but obviously having restriction that we can't perform operations on type 'T'. any alternative?
The problem is that generics don't support operators because they are static methods, and not part of an interface. However, you could probably use Generic Operators, which is available in the Miscellaneous Utility Library.
You would need to add a delegate parameter which performs the multiplication. Something like this
delegate T Multiply<T>(T a, T b);
So then your function would be defined like this:
static T Factorial<T>(T n, Multiply func)
{
... your code here
}
So when your factorial function is called, the caller would pass in the multiplication function:
int x = Factorial<int>(5, (a,b) => a * b);
There is no easy way to do this. I have seen some solutions that work around the problem, but they are fairly complicated. That said, if you really want to do this here are a few ideas:
If you can use .Net 4, you can cast n to dynamic and then perform the addition. You lose safety, of course - you could get an exception at runtime
You could always manually check the type from within your factorial function: If n is a short, cast to short, if n is a double, cast to double... etc. That is complicated and defeats part of the value of generics, but the outside API at least looks simple.
When's the last time you took the factorial of a string, or a character?
Why do you ever need a factorial of type T????
Besides this has been said numerous (prolly 1 million times now).
When you need to use a generic you need to tell the compiler the type.
For instance what if I had a generic stack class?
C# needs to know the elements type when I create my stack.
Otherwise it makes no sense for:
Stack<T> s = new Stack<T>();
s.Push(????); //how do I add items to the stack if we don't know what T is?
Instead you need to specify:
Stack<int> s = new Stack<int>();
s.Push(5);
s.Push(7);
This isn't specifically addressing your question about making the method generic, but your method as it stands will never return anything other than 1.
Supposing you were only working with integers, it should look like this:
static int Factorial(int n)
{
if (n <= 1)
return 1;
// note the multiplication in this step
return n * Factorial(n - 1);
}
public T Factorial<T>(T a, T b, Multiply<T> delegateMutliply, Difference<T> diffDelegate, BaseCondition<T> baseDelegate)
{
if (!baseDelegate(a, b))
return b;
return delegateMutliply(a, Factorial<T>(diffDelegate(a), b, delegateMutliply, diffDelegate, baseDelegate));
}
int y = p.Factorial(3, 1, (a, b) => a * b, (a) => --a, (a, b) => (a <= b) ? false : true);
Super old question but I'd like to add my 2 cents.
Factorial functions require f* = i
A quick function for the example above is:
class FindFactorial
{
static void Main()
{
Console.WriteLine("Please enter your number: ");
int n = int.Parse(Console.ReadLine());
int factorial = 1;
for (int i = 1; i <= n; i++)
{
factorial *= i;
}
Console.WriteLine(factorial);
}
}

Categories