I recently discovered that there is little difference between a delegate and an event. In fact you can "hook" multiple functions into a single Func<T>, for example:
Func<int> mFunction;
...
Func<int, int> getValue = value => {
Console.WriteLine("assigning {0}", value);
return value;
};
mFunction += () => getValue(6);
mFunction += () => getValue(5);
...
int x = 0;
Func<int> function = mFunction;
if (function != null)
x = function();
Console.WriteLine(x);
This calls each "hooked" function, and assigns each value to x in sequence, and x ends up with the last value assigned. In other words, the output is:
assigning 6
assigning 5
5
Is there a way to retrieve all of the return values of these function calls?
You can loop through each Func<int> in the GetInvocationList() method of your object:
foreach(Func<int> f in function.GetInvocationList())
{
var y = f();
//y holds the result
}
Per default, you only get the last return value. However, you can fetch all delegates using GetInvocationList() and then call each individually.
See Calling delegates individually?
Related
I am learning C# myself and I wonder if C# method can quickly parse a list of values just like Python does as below:
def myMethod(somevalue):
return somevalue * 2
x = [1,2,3,4,5]
a = [myMethod(i) for i in x]
Currently I am trying to make a class that has a method that takes in a double.
But what if x is a list?
class myClass
{
public double somevalue;
public myClass(double someValue)
{
somevalue = someValue;
}
public double myMethod()
{
return somevalue * 2;
}
}
myClass output = new myClass(x);
A = output.myMethod();
My question is, can C# create very concise codes that makes the Method takes in the list, loop through the list and gives out a list of results?
Not a python expert but this:
def myMethod(somevalue):
return somevalue * 2
x = [1,2,3,4,5]
a = [myMethod(i) for i in x]
Looks like it would be this in C#:
//either:
double TimesTwo(double d) => d * 2; //a method declaration that is "expression bodied" style
//or:
double TimesTwo(double d) { return d * 2; } //a method declaration that is "normal" style
void SomeOtherMethod(){ //these statements can't just be floating around in a namespace like the method declarations above, they have to be inside some other method
var x = new[] {1d,2,3,4,5}; //the first element is a double (1d), the others will be promoted from int to double without needing an explicit cast, the whole array x is a double[]
var a = x.Select(TimesTwo).ToArray();
}
You can skip creating a separate method for the * 2 operation (the method above is called TimesTwo) and just put the logic of what you want inline:
var x = new[] { 1d,2,3,4,5 };
var a = x.Select(p => p * 2).ToArray();
The p => p * 2 is something like an "inline method" - we refer to them as lambdas; the input argument is called p and its type is inferred from the type of the collection that .Select is called on. In this case a double is inferred, because x is a double array
The return keyword is not specified in a single line lambda (which we refer to as an expression bodied something); the single line of code after the => (in both p => ... and TimesTwo(int i) => ...) is a statement that resolves to a value, and that value is implicitly returned. In this case the statement p => p * 2 multiplies input p by 2 and the result is returned automatically.
The result of the .Select method is an enumerable (specifically of type IEnumerable<double>, and the ToArray() method will enumerate it and turn it into an array. It is the calling of ToArray that causes p*2 to be invoked on every member, and ToArray collects all the results and outputs an array
All this code comes from extension methods in the System.Linq namespace, so your code needs using System.Linq; at the top
One important point, that may well bite at some time in the future; the code in the lambda within the Select is not performed if the enumerable output by the Select is not actually enumerated. If you had:
var enumerableThing = oneThousandThings.Select(p => SomeOperationThatTakesOneSecond(p));
It would execute near instantly; nothing in that line of code enumerates the resulting enumerable, no memory is allocated for a new array, no looping over collections of anything occurs, the operation that takes 1 second is not even called once let alone a thousand times.
If you later did something that actually enumerated the result, then the operation would take a thousand seconds:
var arr = enumerableThing.ToArray() //takes 1000s
foreach(var x in enumerableThing) //would take 1000s to finish looping
...
int i = 500;
foreach(var x in enumerableThing){ //would take 500s, the enumeration quitting early after being half done
i--;
if(i == 0) break;
}
This enumerating could be done hours or days later; it's called deferred execution and is worth looking into further if you're not familiar with it
You would use System.Linq.Enumerable.Where() to filter the List
var filtered = x.Where(y => myMethod(y)).ToList();
or Select to convert the list
var converted = x.Select(y => myMethod(y)).ToList();
I am curious as to what is the point of creating instances of delegates. I understand that they are function pointers but what is the purpose of the using delegate instances?
public delegate bool IsEven(int x);
class Program
{
static void Main(string[] args)
{
int[] nums = new int[] { 1, 3, 4, 5, 6,7, 8, 9 };
// creating an instance of delegate and making it point to 'CheckEven' function
IsEven isEven = new IsEven(CheckEven);
// using delegate for parameter to get sum of evens
int tot1 = Sums(nums, isEven);
// passing in the function directly as parameter and not delegate instance
int tot2 = Sums(nums, CheckEven);
// using lambda expressions
int tot3 = Sums(nums, x=> x%2==0);
ReadKey();
}
public static int Sums(int[] nums, IsEven isEvenOdd)
{
int sum = 0;
foreach(int x in nums)
{
if (isEvenOdd(x))
sum += x;
}
return sum;
}
public static bool CheckEven(int x)
{
if (x % 2 == 0)
return true;
else
return false;
}
}
At first thought opting to always use lambdas seems like the best idea if the functionality of the function you are going to pass does not have complex implementation, otherwise why wouldn't I just pass my function directly into the parameters? Also with Lambdas it is much easier to change it to compute the sum of odds as oppose to creating an entire new method as I would have to with delegates.
You already used delegates even if you passed the method directly, the Sums method could not receive the method name if it's not set its expectation by the delegate definition.
Consider changing the delegate name to public delegate bool EvenOddStatus(int x);
you can send either your CheckEven method or this method:
public static bool CheckOdd(int x)
{
if (x % 2 != 0) // here changed
return true;
else return false;
}
(of course you can use lambda here, but not in more complicated scenarios)
Now your Sums method can sum up either odd or even numbers based on the calling code (either pass CheckEven or CheckOdd).
Delegates are pointers to methods. you define how the code want the method to receive and return, and the calling code can pass a pre-defined implementation later, either a method or delegate.
What if your Main is another method that doesn't know what to sum, odds or evens? it will have a delegate from a calling code up the stack.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C# - The foreach identifier and closures
From Eric Lippert’s blog: “don’t close over the loop variable”
I'm using a lambda expression as ThreadStart parameter, to run a method in a new thread using Thread class. This is my code:
delegate void del();
static void Do(int i)
{
Console.WriteLine(i);
}
static del CreateLoop(del Do)
{
return () =>
{
while (true)
{
Do();
Thread.Sleep(500);
}
};
}
static void Main(string[] args)
{
int n = 0;
var loop = CreateLoop(() => Do(n));
new Thread(() => loop()).Start();
Thread.Sleep(500);
n = 1;
}
And this is the output:
0
1
1
1
...
How is it possible?
Why if I change the value of my integer variable n, also changes the value of i (Do's parameter)?
You should make a different variable out of it, thus not changing the original value.
After all, all you're really doing is calling that same old 'function', the lambda expression passing the variable i over and over again, which indeed changes. It's nog like you're storing the initial value of the var i somewhere.
var loop = CreateLoop(() => Do(n));
This line is simply creating a new function and assigning it to a variable. This function, among other things, passes the value n to the Do function. But it's not calling the Do function, it's just creating a function which will, when executed, call the Do function.
You then start a new thread which calls the function, etc, but your new thread is still executing Do(n), passing the n variable to Do. That part doesn't change - you've created a function which references a particular place in memory (represented by the variable n) and continues to reference that place in memory even as you change the value which is stored there.
I believe the following would "fix" your code:
var loop = (int x) => () => CreateLoop(() => Do(x));
new Thread(loop(n)).Start();
This passes the value of n to the function represented by loop, but the loop function creates a new place in memory (represented by x) in which to store the value. This new place in memory is not affected by subsequent changes to n. That is to say, the function you've created does not directly reference the place in memory to which n is a pointer.
I have a Multiple target
Func<int,int,int> funHandler=Max;
funHandler+=square;
When i execute
Console.WriteLine(funHandler(10,10)); it return the square of 10 (i.e) 200.It did not fire Max.
i used something like
foreach(var v in funHandler.GetInvocationList())
{
Console.WriteLine(v(10,20));
}
'V' is a variable,but it is used like a method.How can i fire all methods that is in delegate's
invocation list?
Well, may be Max has no side effects and you can't notice it? When you execute multicast delegate it returns result of only last delegate.
Try this:
Func<int, int, int> funHandler = (x, y) => { Console.WriteLine(x); return x; };
funHandler += (x, y) => { Console.WriteLine(y); return y; };
int res = funHandler(1, 2);
Console.WriteLine(res);
See? it works
To use invocation list do this:
foreach (var v in funHandler.GetInvocationList())
{
((Func<int, int, int>)v)(1, 2);
}
Or:
foreach (Func<int, int, int> v in funHandler.GetInvocationList())
{
v(1, 2);
}
Multicast with a delegate that returns something doesn't make much sense to me. I'd guess it executes all of them but discards all results but one.
Ok, very silly question.
x => x * 2
is a lambda representing the same thing as a delegate for
int Foo(x) { return x * 2; }
But what is the lambda equivalent of
int Bar() { return 2; }
??
Thanks a lot!
The nullary lambda equivalent would be () => 2.
That would be:
() => 2
Example usage:
var list = new List<int>(Enumerable.Range(0, 10));
Func<int> x = () => 2;
list.ForEach(i => Console.WriteLine(x() * i));
As requested in the comments, here's a breakdown of the above sample...
// initialize a list of integers. Enumerable.Range returns 0-9,
// which is passed to the overloaded List constructor that accepts
// an IEnumerable<T>
var list = new List<int>(Enumerable.Range(0, 10));
// initialize an expression lambda that returns 2
Func<int> x = () => 2;
// using the List.ForEach method, iterate over the integers to write something
// to the console.
// Execute the expression lambda by calling x() (which returns 2)
// and multiply the result by the current integer
list.ForEach(i => Console.WriteLine(x() * i));
// Result: 0,2,4,6,8,10,12,14,16,18
You can just use () if you have no parameters.
() => 2;
The lmabda is:
() => 2