Chaining Actions in C# - c#

I am trying to chain a bunch of functions calls into one callback function ptr (using Action) and each of those function calls take different arguments (so can't use delegates which would be ideal, unless I am missing something :)) So this is what I did:
for (int i=0; i<num_func_calls; ++i)
{
// could be anything different for each call
int call_id = i;
Action old_action = lastAction;
lastAction = new Action(() =>
{
FuncCall(call_id, true);
old_action();
});
}
It works as I expect it to, but the question is: is this efficient/correct? Are there any gotcha's or things I need to worry about with this?
Thanks!

Here is an example using higher order functions.
static Action Apply(IEnumerable<int> data)
{
Action zero = () => { };
return data.Aggregate(zero,
(a, id) => a + (() => FuncCall(id, true)));
}

This would be a great case to use a Task, since it has .ContinueWith which tells the task to run another task when it's complete. You can chain them together.
http://msdn.microsoft.com/en-us/library/dd270696.aspx
Also, you could reduce the delegate use by doing this:
() => {
for (int i=0; i<num_func_calls; ++i) FuncCall(i, true);
}

I'm not entirely sure what it is you're asking but I'm just going to address a couple of things in your post which are wrong.
Firstly; Action is a Delegate it's just one that accepts a single parameter and does not return a value. If I have some Action call it A - Delegate d = A; will compile and run.
Secondly, to pass args in a general manner (meaning to some arbitrary function) you can use DynamicInvoke and wrap your arguments in an object array. As long as the items in the array are of the right types and are in the right order the method will correctly execute. Otherwise it will throw.
DynamicInvoke has a specific application but as an example if you provide me with an Object[] and a Delegate I can use DynamicInvoke to invoke the function without knowing what it's definition is. Like;
myDelegate.DynamicInvoke(args); // where args is an Object[]
In general, you only want to use it when you're deciding which delegates to call at run time.

Related

Call random method directly instead of using a lot of if-statements, C#

Relative newcomer to c# here.
Let’s say I have 50 different methods a1(), a2(), … a50() and I want to call a random one. One way to do it is of course to generate a random int, nr, between 1 and 50 and then use a lot of if statements like if(nr == 1){
a1()
} and so on. Quite cumbersome - can I do something smarter?
Is it for example possible to do something along the lines of creating a string which is initially only “a” and then adding nr as a string and then calling that string as method? Like this:
Public void RandomMethod()
{
nr = Random.Range(1,51);
string = ‘a’ + nr.tostring();
string();
}
I know this doesn’t work, but something like this instead of my first idea would save me hundreds of lines of code
Any response is appreciated 😊
One option would be to put your functions into a collection, say a List for example. Then you could randomly index into that collection to get a random function to call. You would generate a random index between 0 and the length of the List minus 1. This could apply generally to any number of functions then (50 or otherwise).
To do exactly what you asked (and, I have no clue why you'd want to), consider something like this:
Create a delegate that matches the call signature of all of your methods (they all have to have the same call signature or ... I really can't imagine what you'd want to do if they didn't). You could use an Action or Func declaration, but I'm going to make it clear here:
public delegate void SomeMethod(int i);
Then write your 50 methods. All their call signatures will match the delegate:
public static void Method1(int i) { System.Console.WriteLine($"{nameof(Method1)}: {i}"); }
public static void Method2(int i) { System.Console.WriteLine($"{nameof(Method2)}: {i}"); }
public static void Method3(int i) { System.Console.WriteLine($"{nameof(Method3)}: {i}"); }
public static void Method4(int i) { System.Console.WriteLine($"{nameof(Method4)}: {i}"); }
// ...
public static void Method50(int i) { System.Console.WriteLine($"{nameof(Method50)}: {i}"); }
Then create an array of delegates:
public static SomeMethod[] Methods = new SomeMethod[]
{
Method1,
Method2,
Method3,
Method4,
//...
Method50,
};
And then a method that picks 1 or more from the list at random and runs them:
public void Run5RandomMethods()
{
Random random = new Random();
for(int i = 0; i < 5; i++)
{
var randNumber = random.Next(50);
var method = Methods[randNumber];
method.Invoke(i);
}
}
Note: this is untested, I'm not going to create 50 dummy methods for you. If you find an issue, comment below and I'll fix the code
By the way, what you show in your question (composing the name of the method by concatenating a string and the string representation of a number) is doable using a technology known as Reflection. Let me know if you really want to do that.
So, assuming we have fifty methods that all have a signature like
void SomeMethod()
{
...
}
You could declare an array like below, this is an array of Action delegates
var methods = new Action[]
{
SomeMethod,
SomeOtherMethod,
() => _ = SomeFunctionWithAHardcodedParameter("Wibble"),
...
}
Then you could call a random method by doing,
method[Random.Next(methods.Length)]();
First off, I just want to say something similar to what others have already said: you should readdress whether you need 50 methods named a1(), a2(), ..., a50(), and rethink what the problem you're trying to solve is (which you haven't provided enough information for us to help you with).
If that was hyperbole, try to avoid doing that; it may muddy the responses to solve a perceived problem ("why do you have 50 poorly-named methods?") instead of your actual problem ("can I execute a randomly selected method?" <- still a weird question, but who am I to judge...).
That out of the way, you can use something like Reflection. This can be "dangerous" and expensive when executing, so use with caution... or better yet don't use it, but be aware of it, because it can lead you to think Reflection is the answer to problems you don't actually have.
Anyway, you can:
// have an instance of an object
var obj = new ClassName();
// get all the methods of the object
var methodInfos = typeof(ClassName).GetMethods();
// filter them somehow
var filteredMethodInfos = methodInfos.Where(m => Regex.IsMatch(m.Name, #"\a[\d]{1,2}")).ToArray();
// get a random one and invoke it
var rnd = new Random();
filteredMethodInfos[rnd.Next(filteredMethodInfos.Length)].Invoke(obj, null);
I haven't tested this, but it should in theory work.
But again: don't use reflection if you don't have to. There's probably an issue with your root question (as Tim Schmelter said, this is an "XY-problem") if your answer is "randomly execute 1 of 50 methods".

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.

Should method that get Task and passes it away await it?

I have two following methods
public async Task<bool> DoSomething(CancellationToken.token)
{
//do something async
}
//overload with None token
public /*async*/ Task<bool> DoSomething()
{
return /*await*/ DoSomething(CancellationToken.None);
}
Should second method be marked with async/await keywords or not?
It doesn't need to - if you use await/async in the second method, you'll be adding extra overhead which accomplishes nothing, in this case.
The async work inside of DoSomething(CancellationToken) will already provide the proper asynchronous handling and marshaling back to the existing context for you.
At the end of the day, async and await are really just language features which make it easy to create and compose a Task. If you already have a perfectly good Task to return, there is no need to use extra language support to unwrap and rewrap it into a new Task.
To add to Reed's good answer, think about it this way:
Func<int, int> GetFunc()
{
Func<int, int> f = GetFunc(someParameter);
Should you say
return f;
or reason "I'm supposed to be returning a func here, so let's make a lambda that calls the func I have in hand":
return (int i) => f(i);
I hope you would do the former; you already have a Func<int, int> in hand, so just return it. Don't make a func that calls a func.
If you had
IEnumerable<int> GetSequence()
{
IEnumerable<int> sequence = GetSequence(someParameter);
would you say
return sequence;
or
foreach(int item in sequence) yield return item;
? Again, I hope you would do the former. You have a sequence in hand, so why go to all the trouble of making a new sequence that enumerates the old one?
The same goes for tasks; just like you can make a delegate that wraps another delegate and a sequence that wraps another sequence, you can make a task that wraps another task, but why would you? It's just a waste of resources.

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.

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