Reputation: 3381
I'm having problems getting my head around Action delegates in C#
I've looked at this question and I understand the examples there, but in the codebase that I'm working on it's used in a way that I don't quite get. This is the method using the action delegate:
public static string RenderTemplate<T>(string templatePath, T data)
{
string result = null;
ExecuteRazorMethod(() =>
{
result = Razor.Run(data, templatePath);
});
return result;
}
The call to ExecuteRazorMethod() will invoke the following method:
private static void ExecuteRazorMethod(Action a)
{
try
{
a();
}
.
.
.//irrelevant code
.
}
I don't understand what happens when a() is executed. What method is invoked? I've tried debugging it, and the value of a passed into the method is : Void <RenderTemplate> b__5
I don't get that. I need to know what actually happens to the two parametes in RenderTemplate but not understanding what/where the a()
executes makes it hard. Is it maybe something about Anonymous types that I don't understand?
Upvotes: 2
Views: 262
Reputation: 68750
That code will be compiled to something more or less similar to this, I hope it becomes clear now:
[CompilerGenerated]
internal class Closure<T>
{
public string Result {get; private set;}
private readonly string _templatePath;
private readonly T _data;
public Closure(string templatePath, T data)
{
_templatePath = templatePath;
_data = data;
}
public void DelegateMethod()
{
Result = Razor.Run(_data, _templatePath);
}
}
public static string RenderTemplate<T>(string templatePath, T data)
{
Closure<T> closure = new Closure<T>(templatePath, data);
ExecuteRazorMethod(closure);
return closure.Result;
}
private static void ExecuteRazorMethod<T>(Closure<T> closure)
{
try
{
closure.DelegateMethod();
}
.
.
.//irrelevant code
.
}
Upvotes: 2
Reputation: 1241
The compiler actually creates a named method from the
{ result = Razor.Run(data, templatePath); }
part. That is the Void <RenderTemplate> b__5
method. Remember anonymous types and methods are compiler magic (or syntactic sugar if you prefer), i.e. a C# feature, not a CLR feature. The compiler has to translate them into something the CLR understands.
When the delegate is created, it captures the data and templatePath variables, so it can access them when it's executed. That part is commonly known as closure.
Upvotes: 2
Reputation: 504
When a
executes in ExecuteRazorMethod
, it executes exactly the delegate you pass as a
to ExecuteRazorMethod
. Try to toggle the breakpoint at this line result = Razor.Run(data, templatePath);
in this piece of code:
ExecuteRazorMethod(() =>
{
result = Razor.Run(data, templatePath);
});
You will see, that when a
starts to execute, your breakpoint will hit.
Upvotes: 3