TheRedEye Ответов: 1

Вопрос о делегатах


Я думал, что понимаю делегатов, но я явно не понимаю, так как этот код дает мне результат, отличный от того, что я ожидал. Почему вызов не вызывает исключение NullRefenceException после того, как мы назначаем speaker null или новому экземпляру? Может быть, это потому, что сборщик мусора не имел возможности очистить вещи?

Что я уже пробовал:

void Main()
{
	var speaker = new Speaker();
	Action action = new Action(speaker.SayName);
	
	speaker.Name = "Luke";
	action.Invoke(); // outputs "My name is Luke"
	
	speaker.Name = "Leia";
	action.Invoke(); // outputs "My name is Leia"
	
	speaker = null;
	action.Invoke(); // outputs "My name is Leia"
	
	speaker = new Speaker();
	speaker.Name = "Chewy";
	action.Invoke(); // outputs "My name is Leia"
}


class Speaker
{
	public string Name { get; set; }
	
	public void SayName()
	{
		Console.WriteLine($"My name is {Name}");
	}
}

1 Ответов

Рейтинг:
4

F-ES Sitecore

// this creates a Speaker object in memory (let's say at address 10000)
// and creates a speaker variable that references that object (at address 10000)
var speaker = new Speaker();
// This creates an Action with a target that is the SayName method on the object
// at memory address 10000
Action action = new Action(speaker.SayName);

// ...

// this stops speaker pointing to memory address 10000 but the
// object at 10000 (the Speaker object) still exists, so the SayName
// method that Action is referencing also still exists
speaker = null;
// this does what it always has done, calls SayName on the object at address 10000
action.Invoke(); // outputs "My name is Leia"

// setting a variable to null only destroys that object (during GC) if nothing else
// is referencing that object.  However as the Action is referencing the
// object at address 10000 it is not destroyed.


Sandeep Mewara

5!

Sandeep Mewara

Кроме того, "это потому, что сборщик мусора не имел возможности очистить вещи?"
Этот адрес не будет очищен, так как на него все еще ссылается действие.

F-ES Sitecore

GC никогда не очистит его, так как у него есть активная ссылка. До тех пор, пока объект действия больше не существует в любом случае.

CPallini

5.