Click here to Skip to main content
13,801,663 members
Rate this:
 
Please Sign up or sign in to vote.
See more:
Hello Code Project Gurus

I know it is possible to have delegates operate with values that are known at the time the delegate is called - that's simply a parameter
e.g.
   Func<double, double> areaOfCircle = r => Math.PI * Math.Pow(r, 2); 
   Func<double, double> diameterOfCircle = r => 2 * Math.PI * r;
   
   var iNeed = diameterOfCircle;
// -----------------------------
   Console.WriteLine(iNeed(5));    // output is 31.4159265358979
   Console.WriteLine(iNeed(10));   //           62.8318530717959
		
   iNeed = areaOfCircle; 
// ---------------------
   Console.WriteLine(iNeed(5));    // output is 78.5398163397448
   Console.WriteLine(iNeed(10));   //           314.159265358979

I am wondering if there is any way to dynamically create delegates so that each delegate operates using values that are known at runtime when the delegate is created (not when the delegate is called).

So, using the example above, is there a way tell areaOfCircle to use some other factor rather than pi? Something akin to
   Func<double, double> areaOfCircle = r => ::factor:: * Math.Pow(r, 2); 
   Func<double, double> diameterOfCircle = r => 2 * ::factor:: * r;
   
   var iNeed = diameterOfCircle(factor::3);   
// ----------------------------------------
   Console.WriteLine(iNeed(5));    // output is 30
   Console.WriteLine(iNeed(10));   //           60
		
   iNeed = areaOfCircle(factor::3.14); 
// -----------------------------------
   Console.WriteLine(iNeed(5));    // output is 78.5
   Console.WriteLine(iNeed(10));   //           314

Again, I know that a simple example like this is easily solvable by passing the factor to each function in the Console.WriteLine calls. But instead, imagine that the assignment to iNeed and the calls to iNeed are occurring in separate methods, or even classes; that once iNeed is assigned, it is passed as the return value to a calling class that sticks it in a List, which gets called by another class to execute the function... normal, everyday type of stuff.

What I am looking for is a way to set up the functions to operate with a certain factor when the assignment to iNeed is made. Is such a thing possible?

What I have tried:

Searching the net.
Reading MS documentation on delegates, anonymous delegates, dynamic variables, etc.
Posted 6-Dec-18 9:03am
Updated 7-Dec-18 4:09am
v2
Rate this: bad
 
good
Please Sign up or sign in to vote.

Solution 2

Something like this would work:
Func<double, Func<double, double>> factoredAreaOfCircle = factor => r => factor * Math.Pow(r, 2);
Func<double, Func<double, double>> factoredDiameterOfCircle = factor => r => 2 * factor * r;

Func<double, double> iNeed = factoredDiameterOfCircle(3);
Console.WriteLine(iNeed(5));  // Output is 30
Console.WriteLine(iNeed(10)); // Output is 60
		
iNeed = factoredAreaOfCircle(3.14); 
Console.WriteLine(iNeed(5));  // Output is 78.5
Console.WriteLine(iNeed(10)); // Output is 314

Currying vs partial function application | Jon Skeet's coding blog[^]
  Permalink  
Comments
Member 8366403 7-Dec-18 11:48am
   
T E R R I F I C ! ! !
Thank you, Richard. This is exactly what I wanted.

Last night I was thinking about how I had constructed my example for the question and realized that I could have done better. When I saw your answer this morning I tested it using my new model:
Func<double, Func<double, double>> areaOfCircle = factor => r => { Console.WriteLine("area factor is {0}", factor); return (double)(factor * Math.Pow(r, 2)); }; 
Func<double, Func<double, double>> diameterOfCircle = factor => r => { Console.WriteLine("diameter factor is {0}", factor); return (double)(2 * factor * r); };		

var funcList = new List<Func<double, double>>() 
{
	diameterOfCircle(Math.PI),
	areaOfCircle(Math.PI),
	diameterOfCircle(3),
	areaOfCircle(3.14),
};

foreach(var iNeed in funcList)
{
	//Console.WriteLine(iNeed(5));
	Console.WriteLine(iNeed(10));
}

It worked perfectly.

And the article by Jon Skeet explained the workings and background very well.
Thanks again.
Rate this: bad
 
good
Please Sign up or sign in to vote.

Solution 1

You cannot change the delegate definition at runtime.

A delegate is nothing but a pointer to a function. The parameter list of the delegate must match the parameter list of the function that it points to. If it doesn't you can unbalance the stack as the call is pushing parameters on the stack and the function you're calling is popping them off the stack not as they were pushed on.

The concept is called "self modifying code" and is stupid difficult to implement properly in production quality code. I don't ever recommend doing it.

What you are really talking about is just adding an optional parameter to your function, the default value of which is PI.
double CalculateAreaCircle(double r, double factor = Math.PI);
  Permalink  

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month


Advertise | Privacy | Cookies | Terms of Service
Web01 | 2.8.181215.1 | Last Updated 7 Dec 2018
Copyright © CodeProject, 1999-2018
All Rights Reserved.
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100