How does MethodInvoker gets access to members outside its scope? - c#

public void SomeMethod()
{
List<string> someList = LoadList();
if(condition)
{
MethodInvoker invokeThis = delegate {
someList.Remove(0);
};
if(this.InvokeRequired)
{
this.invoke(invokeThis);
}
else
{
invokeThis();
}
}
}
What I dont understand is how does invokeThis gets access to someList. Shouldnt the scope be limited to delegate { .. };.

No, the access shouldn't be limited to the delegate { ... } block. This is a large part of the benefit of anonymous functions (anonymous methods and lambda expressions) - they're able to capture local variables as part of their environment. In this way they implement closures for C#. Note that these really are variables - if you change the value within the delegate, and then access it within the rest of the method again, you'll see the new value. The variable can live on even after the method has returned, and you can even have multiple "instances" of a local variable - one each time the declaration is logically executed.
See section 7.15.5.1 of the C# 4 spec for more details.

When you have an anonymous delegate or lambda that accesses variables from the function that defines it, the C# compiler automatically restructures your code.
Specifically, it generates a class to hold the locals of that method that is passed to the lambda. You can see this if you inspect the generated code using something like ildasm, Reflector or ILSpy.

Related

Linq Expression tree compiling non-trivial object constants and somehow referring to them

Usually, when compiling an expression tree, I would have thought constants which are not primitives types or strings would be impossible. However, this code:
public class A
{ public int mint = -1; }
public static void Main(String[] pArgs)
{
//Run(pArgs);
Action pact = Thing();
pact();
}
public static Action Thing()
{
var a = new A();
a.mint = -1;
LambdaExpression p =
Expression.Lambda<Action>(Expression.Assign(Expression.Field(Expression.Constant(a, typeof(A)), Strong.Instance<A>.Field<int>(b => b.mint)), Expression.Constant(3, typeof(int))));
return ((Expression<Action>)p).Compile();
}
not only compiles but it actually runs! If you run the compiled method in the Thing() method, then you can actually see the variable a change its field from -1 to 3
I don't see how this makes sense/is possible. How can a method refer to a local variable outside its scope (when inspecting the IL of Thing(), the variable a is just a standard local variable, not on the heap like with a closure). Is there some kind of hidden context past around? How can pact run in Main when the local variable a has presumably been removed from the stack!
How can a method refer to a local variable outside its scope
It can't, and it doesn't.
It can sometimes refer to the object the local variable points to though.
Whether it can or not depends on which way the expression is compiled or otherwise used.
There are three ways that Expressions itself will compile an expression into a method:
Compilation with Compile() to IL in a DynamicMethod.
Compilation to IL in with CompileToMethod() (not available in all versions.
Compilation with Compile() into an interpreted set of instructions with a thunk delegate that runs the interpretation.
The first is used if IL compilation is available, unless true is passed to prefer interpretation (on those version with that overload) and interpretation is not also available. Here an array is used for the closure and it is much the same as closing over a local is, in a delegate.
The second is used to write to another assembly and cannot close in this way. Many constants that will work with Compile() will not work with CompileToMethod() for this reason.
The third is used if IL compilation is not available, or true was passed in those versions that have that overload to prefer interpretation. Here a reference to the object is put into an array of "constants" that the interpreter can then refer to.
The other possibility is that something else interprets the expression entirely, e.g. in producing SQL code. Generally this will fail with non-primitive constants other than string though, but if the query processor is aware of the type of the constant (e.g. if it is of a type of entity that it knows about) then code to produce the equivalent to that entity could be produced.
It is only a that is a local variable; the actual object (from new A()) was always on the heap. When you used Expression.Constant(a, typeof(A)), it wasn't a that you put in as a constant - it was the value of a, i.e. the object reference. So: the scope of a is irrelevant as far as the tree is concerned. This is actually exactly how captured variables (closures) are usually implemented by the compiler (although you don't see it usually, and the C#-based expression compiler doesn't allow assignment operators), so as far as the expression tree is concerned: this is business as usual.
As a comparable example using the C# expression compiler, see here, where
public void M() {
int mint = -1;
Expression<Func<int>> lambda = () => mint;
}
compiles to:
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
public int mint;
}
public void M()
{
<>c__DisplayClass0_0 <>c__DisplayClass0_ = new <>c__DisplayClass0_0();
<>c__DisplayClass0_.mint = -1;
Expression.Lambda<Func<int>>(Expression.Field(Expression.Constant(<>c__DisplayClass0_, typeof(<>c__DisplayClass0_0)), FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/)), Array.Empty<ParameterExpression>());
}

Datatype of Methods

Question
How does a delegate store a reference to a function? The source code appears to refer to it as an Object, and the manner in which it invokes the method seems redacted from the source code. Can anyone explain how C# is handling this?
Original Post
It seems I'm constantly fighting the abstractions C# imposes on its programmers. One that's been irking me is the obfuscation of Functions/Methods. As I understand it, all methods are in fact anonymous methods assigned to properties of a class. This is the reason why no function is prefixed by a datatype. For example...
void foo() { ... }
... would be written in Javascript as...
Function foo = function():void { ... };
In my experience, Anonymous functions are typically bad form, but here it's replete throughout the language standard. Because you cannot define a function with its datatype (and apparently the implication/handling is assumed by the compiler), how does one store a reference to a method if the type is never declared?
I'm trying very hard to avoid Delegates and its variants (Action & Func), both because...
it is another abstraction from what's actually happening
the unnecessary overhead required to instantiate these classes (which in turn carry their own pointers to the methods being called).
Looking at the source code for the Delegate.cs, it appears to refer to the reference of a function as simply Object (see lines 23-25).
If these really are objects, how are we calling them? According to the delegate.cs trail, it dead-ends on the following path:
Delegate.cs:DynamicInvoke() > DynamicInvokeImpl() > methodinfo.cs:UnsafeInvoke() > UnsafeInvokeInternal() > RuntimeMethodHandle.InvokeMethod() > runtimehandles.cs:InvokeMethod()
internal extern static object InvokeMethod(object target, object[] arguments, Signature sig, bool constructor);
This really doesn't explain how its invoked if indeed the method is an object. It feels as though this is not code at all, and the actual code called has been redacted from source repository.
Your help is appreciated.
Response to Previous Comments
#Amy: I gave an example immediately after that statement to explain what I meant. If a function were prefixed by a datatype, you could write a true anonymous function, and store it as a property to an Object such as:
private Dictionary<string, Function> ops = new Dictionary<string, Function> {
{"foo", int (int a, int b) { return a + b } }
};
As it stands, C# doesn't allow you to write true anonymous functions, and walls that functionality off behind Delegates and Lambda expressions.
#500 Internal server error: I already explained what I was trying to do. I even bolded it. You assume there's any ulterior motive here; I'm simply trying to understand how C# stores a reference to a method. I even provided links to the source code so that others could read the code for themselves and help answer the question.
#Dialecticus: Obviously if I already found the typical answer on Google, the only other place to find the answer I'm looking for would be here. I realize this is outside the knowledge of most C# developers, and that's why I've provided the source code links. You don't have to reply if you don't know the answer.
While I'm not fully understanding your insights about "true anonymous functions", "not prefixed by a data type" etc, I can explain you how applications written in C# call methods.
First of all, there is no such a thing "function" in C#. Each and every executable entity in C# is in fact a method, that means, it belongs to a class. Even if you define lambdas or anonymous functions like this:
collection.Where(item => item > 0);
the C# compiler creates a compiler-generated class behind the scenes and puts the lambda body return item > 0 into a compiler-generated method.
So assuming you have this code:
class Example
{
public static void StaticMethod() { }
public void InstanceMethod() { }
public Action Property { get; } = () => { };
}
static class Program
{
static void Main()
{
Example.StaticMethod();
var ex = new Example();
ex.InstanceMethod();
ex.Property();
}
}
The C# compiler will create an IL code out of that. The IL code is not executable right away, it needs to be run in a virtual machine.
The IL code will contain a class Example with two methods (actually, four - a default constructor and the property getter method will be automatically generated) and a compiler-generated class containing a method whose body is the body of the lambda expression.
The IL code of Main will look like this (simplified):
call void Example::StaticMethod()
newobj instance void Example::.ctor()
callvirt instance void Example::InstanceMethod()
callvirt instance class [mscorlib]System.Action Example::get_Prop()
callvirt instance void [mscorlib]System.Action::Invoke()
Notice those call and callvirt instructions: these are method calls.
To actually execute the called methods, their IL code needs to be compiled into machine code (CPU instructions). This occurs in the virtual machine called .NET Runtime. There are several of them like .NET Framework, .NET Core, Mono etc.
A .NET Runtime contains a JIT (just-in-time) compiler. It converts the IL code to the actually executable code during the execution of your program.
When the .NET Runtime first encounters the IL code "call method StaticMethod from class Example", it first looks in the internal cache of already compiled methods. When there are no matches (which means this is the first call of that method), the Runtime asks the JIT compiler to create such a compiled-and-ready-to-run method using the IL code. The IL code is converted into a sequence of CPU operations and stored in the process' memory. A pointer to that compiled code is stored in the cache for future reuse.
This all will happen behind the call or callvirt IL instructions (again, simplified).
Once this happened, the Runtime is ready to execute the method. The CPU gets the compiled code's first operation address as the next operation to execute and goes on until the code returns. Then, the Runtime takes over again and proceeds with next IL instructions.
The DynamicInvoke method of the delegates does the same thing: it instructs the Runtime to call a method (after some additional arguments checks etc). The "dead end" you mention RuntimeMethodHandle.InvokeMethod is an intrinsic call to the Runtime directly. The parameters of this method are:
object target - the object on which the delegate invokes the instance method (this parameter).
object[] arguments - the arguments to pass to the method.
Signature sig - the actual method to call, Signature is an internal class that provides the connection between the managed IL code and native executable code.
bool constructor - true if this is a constructor call.
So in summary, methods are not represented as objects in C# (while you of course can have a delegate instance that is an object, but it doesn't represent the executable method, it rather provides an invokable reference to it).
Methods are called by the Runtime, the JIT compiler makes the methods executable.
You cannot define a global "function" outside of classes in C#. You could get a direct native pointer to the compiled (jitted) method code and probably even call it manually by directly manipulating own process' memory. But why?
You clearly misunderstand main differences between script languages, C/C++ and C#.
I guess the main difficulty is that there is no such thing as a function in C#. At all.
C#7 introduced the new feature "a local function", but that is not what a function in JS is.
All pieces of code are methods.
That name is intentionally different from function or a procedure to emphasize the fact that all executable code in C# belongs to a class.
Anonymous methods and lambdas are just a syntax sugar.
A compiler will generate a real method in the same (or a nested) class, where the method with anonymous method declaration belongs to.
This simple article explains it. You can take the examples, compile them and check the generated IL code yourself.
So all the methods (anonymous or not) do belong to a class. It's impossible to answer your updated question, besides saying It does not store a reference to a function, as there is no such thing in C#.
How does one store a reference to a method?
Depending on what you mean by reference, it can be either
An instance of MethodInfo class, used to reference reflection information for a method,
RuntimeMethodHandle (obtainable via RuntimeMethodInfo.MethodHandle) stores a real memory pointer to a JITed method code
A delegate, that is very different from just a memory pointer, but logically could be used to "pass a method reference to another method" .
I believe you are looking for the MethodInfo option, it has a MethodInfo.Invoke method which is very much alike Function..apply function in JS. You have already seen in the Delegate source code how that class is used.
If by "reference" you mean the C-style function pointer, it is in RuntimeMethodHandle struct. You should never use it without solid understanding how a particular .Net platform implementation and a C# compiler work.
Hopefully it clarifies things a bit.
A delegate is simply a pointer(memory location to jump to) to a method with the specified parameters and return type. Any Method that matches the signature(Parameters and return type) is eligible to fulfill the role, irrespective of the defined object. Anonymous simply means the delegate is not named.
Most times the type is implied(if it is not you will get a compiler error):
C# is a strongly typed language. That means every expression (including delegates) MUST have a return type(including void) as well as strongly typed parameters(if any). Generics were created to permit explicit types to be used within general contexts, such as Lists.
To put it another way, delegates are the type-safe managed version of C++ callbacks.
Delegates are helpful in eliminating switch statements by allowing the code to jump to the proper handler without testing any conditions.
A delegate is similar to a Closure in Javascript terminology.
In your response to Amy, you are attempting to equate a loosely typed language like JS, and a strongly typed language C#. In C# it is not possible to pass an arbitrary(loosely-typed) function anywhere. Lambdas and delegates are the only way to guarantee type safety.
I would recommend trying F#, if you are looking to pass functions around.
EDIT:
If you are trying to mimic the behavior of Javascipt, I would try looking at using inheritance through Interfaces. I can mimic multiple inheritance, and be type safe at the same time. But, be aware that it cannot fully supplant Javascript's dependency injection model.
As you probably found out C# doesn't have the concept of a function as in your JavaScript example.
C# is a statically typed language and the only way you can use function pointers is by using the built in types (Func,Action) or custom delegates.(I'm talking about safe,strongly typed pointers)
Javascript is a dynamic language that's why you can do what you describe
If you are willing to lose type safety, you can use the "dynamic" features of C# or refection to achieve what you want like in the following examples (Don't do this,use Func/Action)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace ConsoleApp1
{
class Program
{
private static Dictionary<string, Func<int, int, int>> FuncOps = new Dictionary<string, Func<int, int, int>>
{
{"add", (a, b) => a + b},
{"subtract", (a, b) => a - b}
};
//There are no anonymous delegates
//private static Dictionary<string, delegate> DelecateOps = new Dictionary<string, delegate>
//{
// {"add", delegate {} }
//};
private static Dictionary<string, dynamic> DynamicOps = new Dictionary<string, dynamic>
{
{"add", new Func<int, int, int>((a, b) => a + b)},
{"subtract", new Func<int, int, int>((a, b) => a - b)},
{"inverse", new Func<int, int>((a) => -a )} //Can't do this with Func
};
private static Dictionary<string, MethodInfo> ReflectionOps = new Dictionary<string, MethodInfo>
{
{"abs", typeof(Math).GetMethods().Single(m => m.Name == "Abs" && m.ReturnParameter.ParameterType == typeof(int))}
};
static void Main(string[] args)
{
Console.WriteLine(FuncOps["add"](3, 2));//5
Console.WriteLine(FuncOps["subtract"](3, 2));//1
Console.WriteLine(DynamicOps["add"](3, 2));//5
Console.WriteLine(DynamicOps["subtract"](3, 2));//1
Console.WriteLine(DynamicOps["inverse"](3));//-3
Console.WriteLine(ReflectionOps["abs"].Invoke(null, new object[] { -1 }));//1
Console.ReadLine();
}
}
}
one more example that you shouldn't use
delegate object CustomFunc(params object[] paramaters);
private static Dictionary<string, CustomFunc> CustomParamsOps = new Dictionary<string, CustomFunc>
{
{"add", parameters => (int) parameters[0] + (int) parameters[1]},
{"subtract", parameters => (int) parameters[0] - (int) parameters[1]},
{"inverse", parameters => -((int) parameters[0])}
};
Console.WriteLine(CustomParamsOps["add"](3, 2)); //5
Console.WriteLine(CustomParamsOps["subtract"](3, 2)); //1
Console.WriteLine(CustomParamsOps["inverse"](3)); //-3
I will provide a really short and simplified answer compared to the others. Everything in C# (classes, variables, properties, structs, etc) has a backed with tons of things your programs can hook into. This network of backend stuff slightly lowers the speed of C# when compared to "deeper" languages like C++, but also gives programmers a lot more tools to work with and makes the language easier to use. In this backend is included things like "garbage collection," which is a feature that automatically deletes objects from memory when there are no variables left that reference them. Speaking of reference, the whole system of passing objects by reference, which is default in C#, is also managed in the backend. In C#, Delegates are possible because of features in this backend that allow for something called "reflection."
From Wikipedia:
Reflection is the ability of a computer program to examine,
introspect, and modify its own structure and behavior at runtime.
So when C# compiles and it finds a Delegate, it is just going to make a function, and then store a reflective reference to that function in the variable, allowing you to pass it around and do all sorts of cool stuff with it. You aren't actually storing the function itself in the variable though, you are storing a reference, which is kinda like an address that points you to where the function is stored in RAM.

Passing anonymous/lambda functions to void delegates with no parameters? [C#]

I've been exploring C# delegates and anonymous/lambda functions, and I have some questions about how they interact. From what I understand, a simple delegate object can have predefined return and parameter types, and any named function with those same return/parameter types can be assigned to the delegate.
In my case, however, I've been working on a game where the Player can enqueue multiple Commands into their commandList. At some point after being added to the command list, commands are eventually executed by the player..
I started implementing this by creating specific subclasses for each command (AttackCommand, HealCommand, etc.), but then later found that to be tedious when it came to prototyping a variety of new commands. I thought it would be cool, for testing purposes, to create a CustomCommand class with a member delegate so that I could define and pass functions anonymously and quickly iterate on new game design ideas.
public class CustomCommand : Command {
public delegate void CommandDelegate();
private CommandDelegate func;
public CustomCommand( CommandDelegate del ){
func = del;
}
public Execute(){
func();
}
}
Then Player has a method that defines an anonymous function and uses it to construct a CustomCommand. However, something that confuses me a little bit is the fact that the arguments of this method seem to be able to be stored in the CustomCommand's delegate:
//inside Player class..
//command to steal gold from a target!
public CreateCustomCommand( Player targetPlayer ){
CustomCommand.CommandDelegate anonCommand = delegate()
{
//Steals up to amount passed..
int goldToSteal = targetPlayer.StealGold(25);
gold += goldToSteal;
};
CustomCommand newCommand = new CustomCommand( anonCommand );
commandList.Enqueue( newCommand );
}
//Command is automatically executed later..
I've tried this code, and not only does it compile, but it also works; money is stolen from the target and added to the source player. I'm happy that it works, but it's a little bit unsettling that I'm not sure what exactly is going on behind the scenes..
Here's what I'm having a hard time understanding:
Inside the CreateCustomCommand method (of Player), gold is in scope as it is a member of the Player class, and targetPlayer is in scope because it's a parameter.. But how is it that these things can be wrapped up in a anonymous function and passed to a void, parameterless delegate that's inside another object and still work? What's happening here? Does the creation of an anonymous function store references to all of the objects that it contains?
This seems extremely flexible compared to assigning named functions to delegates with matching return/parameter types, but are there any major drawbacks or pitfalls? Also, is this technique related to (or part of) any particular design pattern or programming methodology?
If I understand this correctly, this works because anonymous functions make use of closures. Closures are blocks of code that can capture (See: Variable Scope In Lambda Expressions) the variable environments in which they were made.
So, because the CreateCustomCommand method defined an anonymous function (a closure), the anonymous function captured and maintained access to the variables that were in scope of CreateCustomCommand.
Thanks to #HansPassant for pointing me in the right direction!

When are properties in closures evaluated?

Several methods in our code base use a 'MaybeObject' that can be passed into functions when a result might be known, or might rely on an external webservice call that has not yet been carried out. For example, the property below can either have a specified known value, or if not specified and called after the async call is complete it will return the result of the Async call.
private string _internalString;
public string stringProp
{
get
{
if (!string.IsNullOrEmpty(_internalString))
return _internalString;
return resultOfAsyncCallFromSomewhereElse;
}
set { _internalString = value; }
}
Obviously, trying to reference the property before the async call is complete would cause a null reference exception so we also have a flag to check if the value is available.
The question is, in the code below would the creation of the lambda try and evaluate stringProp (which might not be populated yet), or would evaluation be deferred until the resulting Action is called (which would be after checking the async operation is complete)?
public Action ExampleMethod(MaybeObject maybe)
{
return () => doSomethingWithString(maybe.stringProp);
}
In C# all would be evaluated whilst execution since C# lambda Closures is not a true Closure which able to resolve a state of captured environment in moment of creation.
() => doSomethingWithString(maybe.stringProp);
Here is even reference maybe could be null and you won't got any issues like NullReferenceException until executing a delegate. This trick sometimes used for late-bound value resolving.
Wikipedia: Closure:
A closure retains a reference to the environment at the time it
was created (for example, to the current value of a local variable
in the enclosing scope) while a generic anonymous function need not do
this.
Nice overview of C# Closure specifics - Anonymous methods and closures in C#
From the definition of Closure it can be inferred that Closure
remembers the values of the variables during its creation. However in
C# the outer local variable (i in this case) is shared with the
anonymous method by creating it on the heap. This means any change to
it in the anonymous method changes the original value and when the
method is called the second time it gets the modified value of i as 1
(see second line of output). This leads many to argue that anonymous
method is not actually a Closure as by its definition the value of a
variable at the time of creation of the Closure should be remembered
and not modifiable.
Evaluation will be deferred until the resulting Action is called.
The code referenced by a delegate is only executed when the delegate itself is explicitly invoked, regardless of how the delegate itself was created.
For example, these ways of passing the code to execute through the Action delegate are all equivalent, and the doSomethingWithString method won't be executed until a call to Action() is made:
Explicit method (.NET 1.1):
private MaybeObject maybe;
public Action ExampleMethod()
{
return new Action(DoSomethingWithMaybeObject);
}
private void DoSomethingWithMaybeObject()
{
doSomethingWithString(maybe.stringProp)
}
Anonymous method (.NET 2.0):
public Action ExampleMethod(MaybeObject maybe)
{
return delegate() { doSomethingWithString(maybe.stringProp) };
}
Lambda (.NET 3.5):
public Action ExampleMethod(MaybeObject maybe)
{
return () => doSomethingWithString(maybe.stringProp);
}
See also:
Delegates
Anonymous Methods
Lambda Expressions
Properties in closures are not evaluated until the action is run because properties are methods, not values. Accessing MyObject.MyProperty is like calling the code MyObject.get_MyProperty(), so you can get different behavior when using a property vs. using the underlying variable.
In .net closures are passed as reference so they are executed as they are evaluated, the same reason you can do something like this.
EventHandler handler = null;
handler = (sender, args) => { // event handler do something};
SomeEvent += handler;
it would be deffered.
ExampleMethod() returns a delegate to the anonymous function () => doSomethingWithString(maybe.stringProp), so doSomethingWithString() won't be called until that delegate is called
You should try this yourself to see what happens!
In this case it seems the closure is really around the MaybeObject, not just the string property (because the object is passed to the Action). The string property is not accessed until the Action is executed.
But even if the string itself were the variable given to the closure...
string s = "";
Func<bool> isGood = () => s == "Good";
s = "Good";
Console.WriteLine(isGood());
// prints 'True'
You can see here that the closure is made around a string, but it isn't evaluated until execution.
Delegates work just like any other function - they don't actually do anything until they are called.

C# Cannot use ref or out parameter inside an anonymous method body

I'm trying to create a function that can create an Action that increments whatever integer is passed in. However my first attempt is giving me an error "cannot use ref or out parameter inside an anonymous method body".
public static class IntEx {
public static Action CreateIncrementer(ref int reference) {
return () => {
reference += 1;
};
}
}
I understand why the compiler doesn't like this, but nonetheless I'd like to have a graceful way to provide a nice incrementer factory that can point to any integer. The only way I'm seeing to do this is something like the following:
public static class IntEx {
public static Action CreateIncrementer(Func<int> getter, Action<int> setter) {
return () => setter(getter() + 1);
}
}
But of course that is more of a pain for the caller to use; requiring the caller to create two lambdas instead of just passing in a reference. Is there any more graceful way of providing this functionality, or will I just have to live with the two-lambda option?
Okay, I've found that it actually is possible with pointers if in unsafe context:
public static class IntEx {
unsafe public static Action CreateIncrementer(int* reference) {
return () => {
*reference += 1;
};
}
}
However, the garbage collector can wreak havoc with this by moving your reference during garbage collection, as the following indicates:
class Program {
static void Main() {
new Program().Run();
Console.ReadLine();
}
int _i = 0;
public unsafe void Run() {
Action incr;
fixed (int* p_i = &_i) {
incr = IntEx.CreateIncrementer(p_i);
}
incr();
Console.WriteLine(_i); // Yay, incremented to 1!
GC.Collect();
incr();
Console.WriteLine(_i); // Uh-oh, still 1!
}
}
One can get around this problem by pinning the variable to a specific spot in memory. This can be done by adding the following to the constructor:
public Program() {
GCHandle.Alloc(_i, GCHandleType.Pinned);
}
That keeps the garbage collector from moving the object around, so exactly what we're looking for. However then you've got to add a destructor to release the pin, and it fragments the memory throughout the lifetime of the object. Not really any easier. This would make more sense in C++, where stuff doesn't get moved around, and resource management is par the course, but not so much in C# where all that is supposed to be automatic.
So looks like the moral of the story is, just wrap that member int in a reference type and be done with it.
(And yes, that's the way I had it working before asking the question, but was just trying to figure out if there was a way I could get rid of all my Reference<int> member variables and just use regular ints. Oh well.)
This is not possible.
The compiler will transform all local variables and parameters used by anonymous methods into fields in an automatically generated closure class.
The CLR does not allow ref types to be stored in fields.
For example, if you pass a value type in a local variable as such a ref parameter, the value's lifetime would extend beyond its stack frame.
It might have been a useful feature for the runtime to allow the creation of variable references with a mechanism to prevent their persistence; such a feature would have allowed an indexer to behave like an array (e.g. so a Dictionary<Int32, Point> could be accessed via "myDictionary[5].X = 9;"). I think such a feature could have been provided safely if such references could not be downcast to other types of objects, nor used as fields, nor passed by reference themselves (since anyplace such a reference could be stored would go out of scope before the reference itself would). Unfortunately, the CLR does not provide such a feature.
To implement what you're after would require that the caller of any function which uses a reference parameter within a closure must wrap within a closure any variable it wants to pass to such a function. If there were a special declaration to indicate that a parameter would be used in such a fashion, it might be practical for a compiler to implement the required behavior. Maybe in a .net 5.0 compiler, though I'm not sure how useful that would be.
BTW, my understanding is that closures in Java use by-value semantics, while those in .net are by-reference. I can understand some occasional uses for by-reference semantics, but using reference by default seems a dubious decision, analogous to the use of default by-reference parameter-passing semantics for VB versions up through VB6. If one wants to capture the value of a variable when creating a delegate to call a function (e.g. if one wants a delegate to call MyFunction(X) using the value of X when the delegate is created), is it better to use a lambda with an extra temp, or is it better to simply use a delegate factory and not bother with Lambda expressions.

Categories