Confused by C# delegate passing as parameter:
class Program
{
static void Main(string[] args)
{
var a = new A();
Action holder = delegate{};
//a.Attach1(holder); //nothing printed
a.Attach2(ref holder);//print as expected
holder();
}
}
public class A
{
private void P1()
{
Console.WriteLine("Inaccessible");
}
public void P2()
{
Console.WriteLine("Accessible");
}
public void Attach1(Action holder)
{
holder += P1;
holder += P2;
}
public void Attach2(ref Action holder)
{
holder += P1;
holder += P2;
}
}
delegate is reference type, why does it still need to be passed with ref in font to work correctly as in Attach2, something like value type?
From C++ experience, delegate is just a function pointer, Attach1(Action holder) is something like Attach1(Action* holder), the origial holder is passed as 'value', thus not assigned, while in the second case, Attach2(ref Action holder) is something like Attach1(Action** holder), the pointer is actually passed, thus can be manipulated correctly. But why in .NET there is no indication or hint???
Because a delegate instance is immutable, and += is a new assignment to a new delegate instance; it is basically:
holder = (Action)Delegate.Combine(holder, P1);
holder = (Action)Delegate.Combine(holder, P2);
If you don't pass that as ref, the new value will not be seen outside the method.
Or to put that in simpler terms - consider a string; a string is likewise immutable and += is an assignment. Now consider:
public void Append(string s) {
s += "[suffix]";
}
public void Append2(ref string s) {
s += "[suffix]";
}
If we call:
string x = "abc";
Append(x);
Console.WriteLine(x);
we will see abc. If we call
string x = "abc";
Append2(ref x);
Console.WriteLine(x);
we will see abc[suffix] - for the exact same reasons.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With