Store methods in an array and call them in C# - c#

In javascript we can do this:
var arr = [];
function fooBar() {
console.log('Hello World');
}
arr[0] = fooBar;
arr[0]();
Essentially each function is a real object and I can store them in an array if I want to. My question is, since C# doesnt have pointers, what is the best way to handle such as scenario? I mean how can I store function references into arrays?
I know we have something called delegates but im not sure if this is the right thing for the task...

Delegates are exactly what you need:
var list = new List<Action>();
...
void fooBar() {
....
}
...
list.Add(fooBar);
The Action is actually nothing but a delegate, simply look its definiton and you´ll see it is similar to a delegate expecting nothing and returning nothing. If you want to pass parameters use any of it´s generic versions, for example Action<T>. If you also need to add methods that return something use the Func-delegate instead.
EDIT: Every delegate has its own type so you can´t mix them and put them alltogether into one single collection, except you use a collection of type Delegate:
var list = new List<Delegate>();
In this case you can´t use urual braces to call the actual delegate, instead you have to use DynamicInvoke and pass the arguments according to the delegates signature.
list[0].DynamicInvoke(args);

Delegates are the right thing for the task - they're equivalent to a strongly-typed function pointer.
Because each delegate is its own type you cannot mix-and-match different delegate types in an array type to a single delegate-type, you can use the parent System.Delegate to allow you to store delegates of different types in the array, though you lose the ability to invoke them directly without some side-channel that informs your program of their arguments.
For example:
public static String Meow(Cat cat) { return "meow"; }
public static String Purr(Cat cat) { return "purr"; }
delegate String CatSound(Cat cat);
CatSound[] catSounds = new CatSound[] {
Meow,
Purr
};
You can then invoke them directly:
Cat orion = new Cat();
catSounds[0]( orion ); // meow
catSounds[1]( orion ); // purr
If you want to add a DogSound delegate to your collection, you'll have a harder job: you need to use Delegate[] instead...
delegate String DogSound(Dog dog);
Delegate[] petSounds = new Delegate[] {
new CatSound( Meow ),
new CatSound( Purr ),
new DogSound( Woof ),
new DogSound( Bark ),
}; // note that C# compiler allows shorthand syntax where simply `Meow` is behind-the-scenes converted into `new CatSound( Meow )`.
...and you have to invoke it using the DynamicInvoke method ( https://msdn.microsoft.com/en-us/library/system.delegate.dynamicinvoke(v=vs.110).aspx ) which means you'll lose compile-time verification of correct arguments, instead any call made with incorrect arguments will fail at runtime with a MemberAccessException.
Dog pupper = new Dog();
Cat orion = new Cat();
petSounds[0].DynamicInvoke( orion );
petSounds[1].DynamicInvoke( orion );
petSounds[2].DynamicInvoke( pupper ); // ok, this is a DogSound
petSounds[3].DynamicInvoke( orion ); // this will fail at runtime because you're passing a Cat into a DogSound delegate
You can also think of delgates as "an interface for a single method".
Prior to the .NET Framework 3.5, you generally needed to define your own delegate types using the delegate keyword (note that the delegate keyword is also overloaded for anonymous functions in C# 3.0), however there is now System.Action and System.Func which serve 95% of cases where you would have previously needed to define your own type. Indeed, today my delegate CatSound is unnecessary, you could just use Func<Cat,String> instead.

Given that the functions to call have the same signature, it could be done by using the predefined generics for delegates as follows.
Func<int,int> Square = x => x*x;
Func<int,int> Successor = x => x+1;
Func<int,int> Functions[] = new Func<int,int>[]{ Square, Successor };
int A = Functions[0](2); // A gets assigned 4;
int B = Functions[1](1); // B gets assigned 2;

You could Store Action or Func objects, someting like:
void Main()
{
var arr = new object[2];
arr[0] = 1;
arr[1] = (Action)DoIt;
foreach (var a in arr)
{
if (a is Action)
{
((Action)a)();
}
else
{
Console.WriteLine(a.ToString());
}
}
}
public void DoIt()
{
Console.WriteLine("did");
}

Consider actions (depending on .net verion)
https://msdn.microsoft.com/en-us/library/018hxwa8(v=vs.110).aspx
List<Action<string>> actions = new List<Action<string>>();
actions.Add(() => {
//do stuff
});
or if you need rturn values use Func: https://msdn.microsoft.com/en-us/library/bb549151(v=vs.110).aspx

yea through delegates you can:
static void iammain()
{
List<Action> lst = new List<Action>();
lst.AddRange(new Action[] { proc1, proc2, proc3 });
for (int i = 0; i < lst.Count; i++)
{
lst[i]();
}
}
static void proc1()
{
Console.WriteLine("i am proc1");
}
static void proc2()
{
Console.WriteLine("i am proc2");
}
static void proc3()
{
Console.WriteLine("i am proc3");
}

Related

Delegate instances vs passing function directly

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.

Where does a local variable get stored so that it's accessible from an asyc delegate? [duplicate]

What is a closure? Do we have them in .NET?
If they do exist in .NET, could you please provide a code snippet (preferably in C#) explaining it?
I have an article on this very topic. (It has lots of examples.)
In essence, a closure is a block of code which can be executed at a later time, but which maintains the environment in which it was first created - i.e. it can still use the local variables etc of the method which created it, even after that method has finished executing.
The general feature of closures is implemented in C# by anonymous methods and lambda expressions.
Here's an example using an anonymous method:
using System;
class Test
{
static void Main()
{
Action action = CreateAction();
action();
action();
}
static Action CreateAction()
{
int counter = 0;
return delegate
{
// Yes, it could be done in one statement;
// but it is clearer like this.
counter++;
Console.WriteLine("counter={0}", counter);
};
}
}
Output:
counter=1
counter=2
Here we can see that the action returned by CreateAction still has access to the counter variable, and can indeed increment it, even though CreateAction itself has finished.
If you are interested in seeing how C# implements Closure read "I know the answer (its 42) blog"
The compiler generates a class in the background to encapsulate the anoymous method and the variable j
[CompilerGenerated]
private sealed class <>c__DisplayClass2
{
public <>c__DisplayClass2();
public void <fillFunc>b__0()
{
Console.Write("{0} ", this.j);
}
public int j;
}
for the function:
static void fillFunc(int count) {
for (int i = 0; i < count; i++)
{
int j = i;
funcArr[i] = delegate()
{
Console.Write("{0} ", j);
};
}
}
Turning it into:
private static void fillFunc(int count)
{
for (int i = 0; i < count; i++)
{
Program.<>c__DisplayClass1 class1 = new Program.<>c__DisplayClass1();
class1.j = i;
Program.funcArr[i] = new Func(class1.<fillFunc>b__0);
}
}
Closures are functional values that hold onto variable values from their original scope. C# can use them in the form of anonymous delegates.
For a very simple example, take this C# code:
delegate int testDel();
static void Main(string[] args)
{
int foo = 4;
testDel myClosure = delegate()
{
return foo;
};
int bar = myClosure();
}
At the end of it, bar will be set to 4, and the myClosure delegate can be passed around to be used elsewhere in the program.
Closures can be used for a lot of useful things, like delayed execution or to simplify interfaces - LINQ is mainly built using closures. The most immediate way it comes in handy for most developers is adding event handlers to dynamically created controls - you can use closures to add behavior when the control is instantiated, rather than storing data elsewhere.
Func<int, int> GetMultiplier(int a)
{
return delegate(int b) { return a * b; } ;
}
//...
var fn2 = GetMultiplier(2);
var fn3 = GetMultiplier(3);
Console.WriteLine(fn2(2)); //outputs 4
Console.WriteLine(fn2(3)); //outputs 6
Console.WriteLine(fn3(2)); //outputs 6
Console.WriteLine(fn3(3)); //outputs 9
A closure is an anonymous function passed outside of the function in which it is created.
It maintains any variables from the function in which it is created that it uses.
A closure is when a function is defined inside another function (or method) and it uses the variables from the parent method. This use of variables which are located in a method and wrapped in a function defined within it, is called a closure.
Mark Seemann has some interesting examples of closures in his blog post where he does a parallel between oop and functional programming.
And to make it more detailed
var workingDirectory = new DirectoryInfo(Environment.CurrentDirectory);//when this variable
Func<int, string> read = id =>
{
var path = Path.Combine(workingDirectory.FullName, id + ".txt");//is used inside this function
return File.ReadAllText(path);
};//the entire process is called a closure.
Here is a contrived example for C# which I created from similar code in JavaScript:
public delegate T Iterator<T>() where T : class;
public Iterator<T> CreateIterator<T>(IList<T> x) where T : class
{
var i = 0;
return delegate { return (i < x.Count) ? x[i++] : null; };
}
So, here is some code that shows how to use the above code...
var iterator = CreateIterator(new string[3] { "Foo", "Bar", "Baz"});
// So, although CreateIterator() has been called and returned, the variable
// "i" within CreateIterator() will live on because of a closure created
// within that method, so that every time the anonymous delegate returned
// from it is called (by calling iterator()) it's value will increment.
string currentString;
currentString = iterator(); // currentString is now "Foo"
currentString = iterator(); // currentString is now "Bar"
currentString = iterator(); // currentString is now "Baz"
currentString = iterator(); // currentString is now null
Hope that is somewhat helpful.
Closures are chunks of code that reference a variable outside themselves, (from below them on the stack), that might be called or executed later, (like when an event or delegate is defined, and could get called at some indefinite future point in time)... Because the outside variable that the chunk of code references may gone out of scope (and would otherwise have been lost), the fact that it is referenced by the chunk of code (called a closure) tells the runtime to "hold" that variable in scope until it is no longer needed by the closure chunk of code...
Basically closure is a block of code that you can pass as an argument to a function. C# supports closures in form of anonymous delegates.
Here is a simple example:
List.Find method can accept and execute piece of code (closure) to find list's item.
// Passing a block of code as a function argument
List<int> ints = new List<int> {1, 2, 3};
ints.Find(delegate(int value) { return value == 1; });
Using C#3.0 syntax we can write this as:
ints.Find(value => value == 1);
If you write an inline anonymous method (C#2) or (preferably) a Lambda expression (C#3+), an actual method is still being created. If that code is using an outer-scope local variable - you still need to pass that variable to the method somehow.
e.g. take this Linq Where clause (which is a simple extension method which passes a lambda expression):
var i = 0;
var items = new List<string>
{
"Hello","World"
};
var filtered = items.Where(x =>
// this is a predicate, i.e. a Func<T, bool> written as a lambda expression
// which is still a method actually being created for you in compile time
{
i++;
return true;
});
if you want to use i in that lambda expression, you have to pass it to that created method.
So the first question that arises is: should it be passed by value or reference?
Pass by reference is (I guess) more preferable as you get read/write access to that variable (and this is what C# does; I guess the team in Microsoft weighed the pros and cons and went with by-reference; According to Jon Skeet's article, Java went with by-value).
But then another question arises: Where to allocate that i?
Should it actually/naturally be allocated on the stack?
Well, if you allocate it on the stack and pass it by reference, there can be situations where it outlives it's own stack frame. Take this example:
static void Main(string[] args)
{
Outlive();
var list = whereItems.ToList();
Console.ReadLine();
}
static IEnumerable<string> whereItems;
static void Outlive()
{
var i = 0;
var items = new List<string>
{
"Hello","World"
};
whereItems = items.Where(x =>
{
i++;
Console.WriteLine(i);
return true;
});
}
The lambda expression (in the Where clause) again creates a method which refers to an i. If i is allocated on the stack of Outlive, then by the time you enumerate the whereItems, the i used in the generated method will point to the i of Outlive, i.e. to a place in the stack that is no longer accessible.
Ok, so we need it on the heap then.
So what the C# compiler does to support this inline anonymous/lambda, is use what is called "Closures": It creates a class on the Heap called (rather poorly) DisplayClass which has a field containing the i, and the Function that actually uses it.
Something that would be equivalent to this (you can see the IL generated using ILSpy or ILDASM):
class <>c_DisplayClass1
{
public int i;
public bool <GetFunc>b__0()
{
this.i++;
Console.WriteLine(i);
return true;
}
}
It instantiates that class in your local scope, and replaces any code relating to i or the lambda expression with that closure instance. So - anytime you are using the i in your "local scope" code where i was defined, you are actually using that DisplayClass instance field.
So if I would change the "local" i in the main method, it will actually change _DisplayClass.i ;
i.e.
var i = 0;
var items = new List<string>
{
"Hello","World"
};
var filtered = items.Where(x =>
{
i++;
return true;
});
filtered.ToList(); // will enumerate filtered, i = 2
i = 10; // i will be overwriten with 10
filtered.ToList(); // will enumerate filtered again, i = 12
Console.WriteLine(i); // should print out 12
it will print out 12, as "i = 10" goes to that dispalyclass field and changes it just before the 2nd enumeration.
A good source on the topic is this Bart De Smet Pluralsight module (requires registration) (also ignore his erroneous use of the term "Hoisting" - what (I think) he means is that the local variable (i.e. i) is changed to refer to the the new DisplayClass field).
In other news, there seems to be some misconception that "Closures" are related to loops - as I understand "Closures" are NOT a concept related to loops, but rather to anonymous methods / lambda expressions use of local scoped variables - although some trick questions use loops to demonstrate it.
A closure aims to simplify functional thinking, and it allows the runtime to manage
state, releasing extra complexity for the developer. A closure is a first-class function
with free variables that are bound in the lexical environment. Behind these buzzwords
hides a simple concept: closures are a more convenient way to give functions access
to local state and to pass data into background operations. They are special functions
that carry an implicit binding to all the nonlocal variables (also called free variables or
up-values) referenced. Moreover, a closure allows a function to access one or more nonlocal variables even when invoked outside its immediate lexical scope, and the body
of this special function can transport these free variables as a single entity, defined in
its enclosing scope. More importantly, a closure encapsulates behavior and passes it
around like any other object, granting access to the context in which the closure was
created, reading, and updating these values.
Just out of the blue,a simple and more understanding answer from the book C# 7.0 nutshell.
Pre-requisit you should know :A lambda expression can reference the local variables and parameters of the method
in which it’s defined (outer variables).
static void Main()
{
int factor = 2;
//Here factor is the variable that takes part in lambda expression.
Func<int, int> multiplier = n => n * factor;
Console.WriteLine (multiplier (3)); // 6
}
Real part:Outer variables referenced by a lambda expression are called captured variables. A lambda expression that captures variables is called a closure.
Last Point to be noted:Captured variables are evaluated when the delegate is actually invoked, not when the variables were captured:
int factor = 2;
Func<int, int> multiplier = n => n * factor;
factor = 10;
Console.WriteLine (multiplier (3)); // 30
A closure is a function, defined within a function, that can access the local variables of it as well as its parent.
public string GetByName(string name)
{
List<things> theThings = new List<things>();
return theThings.Find<things>(t => t.Name == name)[0];
}
so the function inside the find method.
t => t.Name == name
can access the variables inside its scope, t, and the variable name which is in its parents scope. Even though it is executed by the find method as a delegate, from another scope all together.

Execute lambda expression immediately after its definition?

Is there a way to execute a lambda expression immediately after its definition?
In other words (Invalid C# code):
(() => { Console.WriteLine("Hello World"); }).Invoke();
Sure.
new Action(() => { Console.WriteLine("Hello World"); })();
That should do the trick.
Another "option", which is just the other two answers in a slightly different guise:
((Action)(() => { Console.WriteLine("Hello World"); }))();
The reason, as directly taken from phoog's comment:
...you haven't told the compiler whether you want an Action or an Expression<Action>. If you cast that lambda expression to Action, you'll be able to call Invoke on it or use the method-call syntax () to invoke it.
It sure gets ugly though, and I do not know of a place where this form is ever useful, as it cannot be used for recursion without a name...
You should be able to do this:
Action runMe = () => { Console.WriteLine("Hello World"); };
runMe();
Here's an example of how this might be used. You want to initialize a constructor with the result of a few lines of code that can't be written as a function because that is how the 3rd party API is structured.
It is just glue code to prevent writing a standalone function that is never called anywhere else. I'm using Func instead of Action, but the answer is the same as user166390.
// imagine several dozens of lines that look like this
// where the result is the return value of a function call
fields.Add(new ProbeField(){
Command = "A",
Field = "Average",
Value = be.GetAverage()
});
// now you need something that can't be expressed as function call
// so you wrap it in a lambda and immediately call it.
fields.Add(new ProbeField(){
Command = "C",
Field = "Cal Coeff",
Value = ((Func<string>)(() => {
CalCoef coef;
Param param;
be.GetCalibrationCoefficients(out coef, out param);
return coef.lowDet1.ToString();
}))()
});
For my own projects I've sometimes written a tiny reusable helper function to make the syntax for an immediately invoked lambda look shorter. This 'Inv' was inspired by the similar 'fun' function in the LanguageExt library.
// Helper utility functions
public static void Inv(Action a) => a();
public static T Inv<T>(Func<T> f) => f();
private static void TestMethod()
{
// Action example
Inv(() => Console.WriteLine("Hello World!"));
// Func example with no parameters
bool result = Inv(() =>
{
if (1 == 1)
return true;
else
return false;
});
}
You could also extend this with a few other overloads to make it so you could pass in parameters, but these look a bit more cumbersome syntax wise and may not be as helpful.
public static Func<A, T> Inv<A, T>(Func<A, T> f) => f;
public static Func<A, B, T> Inv<A, B, T>(Func<A, B, T> f) => f;
string printNumber = Inv((int number) => $"This is the number {number}")(5);
int addedNumbers = Inv((int x, int y) => x + y)(5, 6);
using System.Threading.Tasks;
using System.Threading;
Task.Run(()=>{
//do something
});
programmers really like to make things more difficult than they should be
You can add a 500ms delay with
Task.Run(()=>{
Thread.Sleep(500);
//do something
});
and then the next logical extension is passing parameters to your anonymous function. You can do this with scope:
var x=1;
Task.Run(()=>{
x++;
});
and then you can basically throw the rest of C# out the window. If you like this functional style, I suggest JS or C.

How does having a dynamic variable affect performance?

I have a question about the performance of dynamic in C#. I've read dynamic makes the compiler run again, but what does it do?
Does it have to recompile the whole method with the dynamic variable used as a parameter or just those lines with dynamic behavior/context?
I've noticed that using dynamic variables can slow down a simple for loop by 2 orders of magnitude.
Code I have played with:
internal class Sum2
{
public int intSum;
}
internal class Sum
{
public dynamic DynSum;
public int intSum;
}
class Program
{
private const int ITERATIONS = 1000000;
static void Main(string[] args)
{
var stopwatch = new Stopwatch();
dynamic param = new Object();
DynamicSum(stopwatch);
SumInt(stopwatch);
SumInt(stopwatch, param);
Sum(stopwatch);
DynamicSum(stopwatch);
SumInt(stopwatch);
SumInt(stopwatch, param);
Sum(stopwatch);
Console.ReadKey();
}
private static void Sum(Stopwatch stopwatch)
{
var sum = 0;
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < ITERATIONS; i++)
{
sum += i;
}
stopwatch.Stop();
Console.WriteLine(string.Format("Elapsed {0}", stopwatch.ElapsedMilliseconds));
}
private static void SumInt(Stopwatch stopwatch)
{
var sum = new Sum();
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < ITERATIONS; i++)
{
sum.intSum += i;
}
stopwatch.Stop();
Console.WriteLine(string.Format("Class Sum int Elapsed {0}", stopwatch.ElapsedMilliseconds));
}
private static void SumInt(Stopwatch stopwatch, dynamic param)
{
var sum = new Sum2();
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < ITERATIONS; i++)
{
sum.intSum += i;
}
stopwatch.Stop();
Console.WriteLine(string.Format("Class Sum int Elapsed {0} {1}", stopwatch.ElapsedMilliseconds, param.GetType()));
}
private static void DynamicSum(Stopwatch stopwatch)
{
var sum = new Sum();
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < ITERATIONS; i++)
{
sum.DynSum += i;
}
stopwatch.Stop();
Console.WriteLine(String.Format("Dynamic Sum Elapsed {0}", stopwatch.ElapsedMilliseconds));
}
I've read dynamic makes the compiler run again, but what it does. Does it have to recompile whole method with the dynamic used as a parameter or rather those lines with dynamic behavior/context(?)
Here's the deal.
For every expression in your program that is of dynamic type, the compiler emits code that generates a single "dynamic call site object" that represents the operation. So, for example, if you have:
class C
{
void M()
{
dynamic d1 = whatever;
dynamic d2 = d1.Foo();
then the compiler will generate code that is morally like this. (The actual code is quite a bit more complex; this is simplified for presentation purposes.)
class C
{
static DynamicCallSite FooCallSite;
void M()
{
object d1 = whatever;
object d2;
if (FooCallSite == null) FooCallSite = new DynamicCallSite();
d2 = FooCallSite.DoInvocation("Foo", d1);
See how this works so far? We generate the call site once, no matter how many times you call M. The call site lives forever after you generate it once. The call site is an object that represents "there's going to be a dynamic call to Foo here".
OK, so now that you've got the call site, how does the invocation work?
The call site is part of the Dynamic Language Runtime. The DLR says "hmm, someone is attempting to do a dynamic invocation of a method foo on this here object. Do I know anything about that? No. Then I'd better find out."
The DLR then interrogates the object in d1 to see if it is anything special. Maybe it is a legacy COM object, or an Iron Python object, or an Iron Ruby object, or an IE DOM object. If it is not any of those then it must be an ordinary C# object.
This is the point where the compiler starts up again. There's no need for a lexer or parser, so the DLR starts up a special version of the C# compiler that just has the metadata analyzer, the semantic analyzer for expressions, and an emitter that emits Expression Trees instead of IL.
The metadata analyzer uses Reflection to determine the type of the object in d1, and then passes that to the semantic analyzer to ask what happens when such an object is invoked on method Foo. The overload resolution analyzer figures that out, and then builds an Expression Tree -- just as if you'd called Foo in an expression tree lambda -- that represents that call.
The C# compiler then passes that expression tree back to the DLR along with a cache policy. The policy is usually "the second time you see an object of this type, you can re-use this expression tree rather than calling me back again". The DLR then calls Compile on the expression tree, which invokes the expression-tree-to-IL compiler and spits out a block of dynamically-generated IL in a delegate.
The DLR then caches this delegate in a cache associated with the call site object.
Then it invokes the delegate, and the Foo call happens.
The second time you call M, we already have a call site. The DLR interrogates the object again, and if the object is the same type as it was last time, it fetches the delegate out of the cache and invokes it. If the object is of a different type then the cache misses, and the whole process starts over again; we do semantic analysis of the call and store the result in the cache.
This happens for every expression that involves dynamic. So for example if you have:
int x = d1.Foo() + d2;
then there are three dynamic calls sites. One for the dynamic call to Foo, one for the dynamic addition, and one for the dynamic conversion from dynamic to int. Each one has its own runtime analysis and its own cache of analysis results.
Make sense?
Update: Added precompiled and lazy-compiled benchmarks
Update 2: Turns out, I'm wrong. See Eric Lippert's post for a complete and correct answer. I'm leaving this here for the sake of the benchmark numbers
*Update 3: Added IL-Emitted and Lazy IL-Emitted benchmarks, based on Mark Gravell's answer to this question.
To my knowledge, use of the dynamic keyword does not cause any extra compilation at runtime in and of itself (though I imagine it could do so under specific circumstances, depending on what type of objects are backing your dynamic variables).
Regarding performance, dynamic does inherently introduce some overhead, but not nearly as much as you might think. For example, I just ran a benchmark that looks like this:
void Main()
{
Foo foo = new Foo();
var args = new object[0];
var method = typeof(Foo).GetMethod("DoSomething");
dynamic dfoo = foo;
var precompiled =
Expression.Lambda<Action>(
Expression.Call(Expression.Constant(foo), method))
.Compile();
var lazyCompiled = new Lazy<Action>(() =>
Expression.Lambda<Action>(
Expression.Call(Expression.Constant(foo), method))
.Compile(), false);
var wrapped = Wrap(method);
var lazyWrapped = new Lazy<Func<object, object[], object>>(() => Wrap(method), false);
var actions = new[]
{
new TimedAction("Direct", () =>
{
foo.DoSomething();
}),
new TimedAction("Dynamic", () =>
{
dfoo.DoSomething();
}),
new TimedAction("Reflection", () =>
{
method.Invoke(foo, args);
}),
new TimedAction("Precompiled", () =>
{
precompiled();
}),
new TimedAction("LazyCompiled", () =>
{
lazyCompiled.Value();
}),
new TimedAction("ILEmitted", () =>
{
wrapped(foo, null);
}),
new TimedAction("LazyILEmitted", () =>
{
lazyWrapped.Value(foo, null);
}),
};
TimeActions(1000000, actions);
}
class Foo{
public void DoSomething(){}
}
static Func<object, object[], object> Wrap(MethodInfo method)
{
var dm = new DynamicMethod(method.Name, typeof(object), new Type[] {
typeof(object), typeof(object[])
}, method.DeclaringType, true);
var il = dm.GetILGenerator();
if (!method.IsStatic)
{
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Unbox_Any, method.DeclaringType);
}
var parameters = method.GetParameters();
for (int i = 0; i < parameters.Length; i++)
{
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldc_I4, i);
il.Emit(OpCodes.Ldelem_Ref);
il.Emit(OpCodes.Unbox_Any, parameters[i].ParameterType);
}
il.EmitCall(method.IsStatic || method.DeclaringType.IsValueType ?
OpCodes.Call : OpCodes.Callvirt, method, null);
if (method.ReturnType == null || method.ReturnType == typeof(void))
{
il.Emit(OpCodes.Ldnull);
}
else if (method.ReturnType.IsValueType)
{
il.Emit(OpCodes.Box, method.ReturnType);
}
il.Emit(OpCodes.Ret);
return (Func<object, object[], object>)dm.CreateDelegate(typeof(Func<object, object[], object>));
}
As you can see from the code, I try to invoke a simple no-op method seven different ways:
Direct method call
Using dynamic
By reflection
Using an Action that got precompiled at runtime (thus excluding compilation time from the results).
Using an Action that gets compiled the first time it is needed, using a non-thread-safe Lazy variable (thus including compilation time)
Using a dynamically-generated method that gets created before the test.
Using a dynamically-generated method that gets lazily instantiated during the test.
Each gets called 1 million times in a simple loop. Here are the timing results:
Direct: 3.4248ms
Dynamic: 45.0728ms
Reflection: 888.4011ms
Precompiled: 21.9166ms
LazyCompiled: 30.2045ms
ILEmitted: 8.4918ms
LazyILEmitted: 14.3483ms
So while using the dynamic keyword takes an order of magnitude longer than calling the method directly, it still manages to complete the operation a million times in about 50 milliseconds, making it far faster than reflection. If the method we call were trying to do something intensive, like combining a few strings together or searching a collection for a value, those operations would likely far outweigh the difference between a direct call and a dynamic call.
Performance is just one of many good reasons not to use dynamic unnecessarily, but when you're dealing with truly dynamic data, it can provide advantages that far outweigh the disadvantages.
Update 4
Based on Johnbot's comment, I broke the Reflection area down into four separate tests:
new TimedAction("Reflection, find method", () =>
{
typeof(Foo).GetMethod("DoSomething").Invoke(foo, args);
}),
new TimedAction("Reflection, predetermined method", () =>
{
method.Invoke(foo, args);
}),
new TimedAction("Reflection, create a delegate", () =>
{
((Action)method.CreateDelegate(typeof(Action), foo)).Invoke();
}),
new TimedAction("Reflection, cached delegate", () =>
{
methodDelegate.Invoke();
}),
... and here are the benchmark results:
So if you can predetermine a specific method that you'll need to call a lot, invoking a cached delegate referring to that method is about as fast as calling the method itself. However, if you need to determine which method to call just as you're about to invoke it, creating a delegate for it is very expensive.

What is the lifetime of a delegate created by a lambda in C#?

Lambdas are nice, as they offer brevity and locality and an extra form of encapsulation. Instead of having to write functions which are only used once you can use a lambda.
While wondering how they worked, I intuitively figured they are probably only created once. This inspired me to create a solution which allows to restrict the scope of a class member beyond private to one particular scope by using the lambda as an identifier of the scope it was created in.
This implementation works, although perhaps overkill (still researching it), proving my assumption to be correct.
A smaller example:
class SomeClass
{
public void Bleh()
{
Action action = () => {};
}
public void CallBleh()
{
Bleh(); // `action` == {Method = {Void <SomeClass>b__0()}}
Bleh(); // `action` still == {Method = {Void <SomeClass>b__0()}}
}
}
Would the lambda ever return a new instance, or is it guaranteed to always be the same?
It's not guaranteed either way.
From what I remember of the current MS implementation:
A lambda expression which doesn't capture any variables is cached statically
A lambda expression which only captures "this" could be captured on a per-instance basis, but isn't
A lambda expression which captures a local variable can't be cached
Two lambda expressions which have the exact same program text aren't aliased; in some cases they could be, but working out the situations in which they can be would be very complicated
EDIT: As Eric points out in the comments, you also need to consider type arguments being captured for generic methods.
EDIT: The relevant text of the C# 4 spec is in section 6.5.1:
Conversions of semantically identical anonymous functions with the same (possibly empty) set of captured outer variable instances to the same delegate types are permitted (but not required) to return the same delegate instance. The term semantically identical is used here to mean that execution of the anonymous functions will, in all cases, produce the same effects given the same arguments.
Based on your question here and your comment to Jon's answer I think you are confusing multiple things. To make sure it is clear:
The method that backs the delegate for a given lambda is always the same.
The method that backs the delegate for "the same" lambda that appears lexically twice is permitted to be the same, but in practice is not the same in our implementation.
The delegate instance that is created for a given lambda might or might not always be the same, depending on how smart the compiler is about caching it.
So if you have something like:
for(i = 0; i < 10; ++i)
M( ()=>{} )
then every time M is called, you get the same instance of the delegate because the compiler is smart and generates
static void MyAction() {}
static Action DelegateCache = null;
...
for(i = 0; i < 10; ++i)
{
if (C.DelegateCache == null) C.DelegateCache = new Action ( C.MyAction )
M(C.DelegateCache);
}
If you have
for(i = 0; i < 10; ++i)
M( ()=>{this.Bar();} )
then the compiler generates
void MyAction() { this.Bar(); }
...
for(i = 0; i < 10; ++i)
{
M(new Action(this.MyAction));
}
You get a new delegate every time, with the same method.
The compiler is permitted to (but in fact does not at this time) generate
void MyAction() { this.Bar(); }
Action DelegateCache = null;
...
for(i = 0; i < 10; ++i)
{
if (this.DelegateCache == null) this.DelegateCache = new Action ( this.MyAction )
M(this.DelegateCache);
}
In that case you would always get the same delegate instance if possible, and every delegate would be backed by the same method.
If you have
Action a1 = ()=>{};
Action a2 = ()=>{};
Then in practice the compiler generates this as
static void MyAction1() {}
static void MyAction2() {}
static Action ActionCache1 = null;
static Action ActionCache2 = null;
...
if (ActionCache1 == null) ActionCache1 = new Action(MyAction1);
Action a1 = ActionCache1;
if (ActionCache2 == null) ActionCache2 = new Action(MyAction2);
Action a2 = ActionCache2;
However the compiler is permitted to detect that the two lambdas are identical and generate
static void MyAction1() {}
static Action ActionCache1 = null;
...
if (ActionCache1 == null) ActionCache1 = new Action(MyAction1);
Action a1 = ActionCache1;
Action a2 = ActionCache1;
Is that now clear?
No guarantees.
A quick demo:
Action GetAction()
{
return () => Console.WriteLine("foo");
}
Call this twice, do a ReferenceEquals(a,b), and you'll get true
Action GetAction()
{
var foo = "foo";
return () => Console.WriteLine(foo);
}
Call this twice, do a ReferenceEquals(a,b), and you'll get false
I see Skeet jumped in while I was answering, so I won't belabor that point. One thing I would suggest, to better understand how you are using things, is to get familiar with reverse engineering tools and IL. Take the code sample(s) in question and reverse engineer to IL. It will give you a great amount of information on how the code is working.
Good question. I don't have an "academic answer," more of a practical answer: I could see a compiler optimizing the binary to use the same instance, but I wouldn't ever write code that assumes it's "guaranteed" to be the same instance.
I upvoted you at least, so hopefully someone can give you the academic answer you're looking for.

Categories

Resources