Вопрос

It seems that adding a delegate to an Action stored into a Dictionary fails when I try do add it through the reference obtained using TryToGetValue method.

Here's an example reproducing the error:

void Foo()
{
  Console.WriteLine("Foo");
}
void Bar()
{   
  Console.WriteLine("Bar");
}

Dictionary<int, Action> dic = new Dictionary<int, Action>();    

dic[3] = delegate{};
dic[3] += Foo;

Action ac;
if (dic.TryGetValue(3,out ac))
{
  Console.WriteLine("Found");
  ac += Bar;
}
dic[3]();

Output:

Found
Foo

The value is found, but it seems that ac and dic[3] are references to different objects (Bar is not printed).

Could anyone explain me what's going on? With what exactly is filled the out parameter? Since Action are classes, shouldn't ac reference point to the same object stored into the Dictionary?

Это было полезно?

Решение

Your example can be simplified (dictionary excluded):

  void Foo() {
    Console.WriteLine("Foo");
  }

  void Bar() {
    Console.WriteLine("Bar");
  }

  ...
  Action x = Foo;
  Action y = x;

  if (Object.ReferenceEquals(x, y))
    Console.WriteLine("x was equal to y"); 

  // creates new delegate instance: 
  // x = x + Bar; 
  //   that is equal to 
  // x = Action.Combine(x, Bar);
  //   so x is not equal to y any longer:
  // x is a combined delegate (Foo + Bar)
  // y is a delegate to Foo (an old version of x)
  //   such a behavior is typical for operators (+, +=, etc.): 
  //   when we declare "public static MyType operator + (MyType a, MyType b)"
  //   it means that a new object "c" will be created that'll equal to sum of a and b 
  x += Bar; 

  if (Object.ReferenceEquals(x, y))
    Console.WriteLine("x is still equal to y");

  y();

The output is:

x was equal to y

Foo

And the cause of such a behaviour is in the += operation algorithm

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top