• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

Нужно ли отписываться от событий

  • Автор темы ][tiger
  • Дата начала
Статус
Закрыто для дальнейших ответов.
T

][tiger

К примеру у нас есть некая типизированная коллекция. У элементов этой коллекции есть какие-то собития, которые эта самая коллекция должна отслеживать (то есть при добавлении элемента происходит подписка).

Нужно ли специально отписываться от таких событий в случае удаления из коллекции одного из элементов (учитывая, что больше никто не содержит ссылок на этот элемент)?

Соберется ли этот объект сборщиком мусора или будет считаться, что коллекция все еще содержит на него ссылку?
 
T

][tiger

Ну и сам уже отвечу :) Если ссылок больше нет, то GC соберет этот объект и без отписки от событий. Ведь на самом деле, это сам объект ссылается на делегат.... Однако, для коллекции все-таки нужно отписаться...
 
D

Dr.Gigabit

<!--QuoteBegin-][tiger+21:03:2006, 17:35 -->
<span class="vbquote">(][tiger @ 21:03:2006, 17:35 )</span><!--QuoteEBegin-->GC соберет этот объект и без отписки от событий
[snapback]32240" rel="nofollow" target="_blank[/snapback]​
[/quote]


<!--QuoteBegin-][tiger+21:03:2006, 17:35 -->
<span class="vbquote">(][tiger @ 21:03:2006, 17:35 )</span><!--QuoteEBegin-->для коллекции все-таки нужно отписаться
[snapback]32240" rel="nofollow" target="_blank[/snapback]​
[/quote]


Не уловил мысли
 
T

][tiger

Мысль такова, что если мы подписаны на событие какого-то объекта, но ссылок больше на него нет, то GC соберет его как мусор.

В случае с коллекцией - если объект удаляют из коллекции (а значит коллекция больше не должна обрабатывать события объекта), то существует вероятность, что ссылка на этот объект у кого-то остается и после удаления из коллекции. Тогда коллекция будет все еще обрабатывать события этого объекта (потому что он не уничтожился).

Сам себе ответил на вопрос потому, что догадался запустить SnippetCompiler набросать пример и проверить - будет ли объект собираться GC, если ссылок нет, но есть подписчики. Ответ - будет.
 
K

karlito

GC соберет этот объект и без отписки от событий

Не уверен. За первый проход нет, за второй - да.

Сам себе ответил на вопрос потому, что догадался запустить SnippetCompiler набросать пример и проверить - будет ли объект собираться GC, если ссылок нет, но есть подписчики. Ответ - будет.

Не ответил на самый главный вопрос - ПОЧЕМУ?
 
T

][tiger

<!--QuoteBegin-karlito+23:03:2006, 17:05 -->
<span class="vbquote">(karlito @ 23:03:2006, 17:05 )</span><!--QuoteEBegin-->Не уверен. За первый проход нет, за второй - да.
[snapback]32375" rel="nofollow" target="_blank[/snapback]​
[/quote]

Я же говорю, что проверил. Собирает. Достаточно объявить деструктор и посмотреть, вызывается ли при вызове GC.Collect(). Так вот - вызывается.


<!--QuoteBegin-karlito+23:03:2006, 17:05 -->
<span class="vbquote">(karlito @ 23:03:2006, 17:05 )</span><!--QuoteEBegin-->Не ответил на самый главный вопрос - ПОЧЕМУ?
[snapback]32375" rel="nofollow" target="_blank[/snapback]​
[/quote]

Опять-таки, ответил. Потому что не подписчик ссылается физически на объект с событием, а объект который содержит событие ссылается на делегаты, которые подписаны на его событие. Я же говорил уже.
 
D

Dr.Gigabit

[tiger,23:03:2006, 18:19 ]
делегаты, которые подписаны на его событие
[snapback]32377" rel="nofollow" target="_blank[/snapback]​


Ужас какой-то :) Примерчик можно в студию?
Но сразу сомнения хотя бы в том, что частный случай не подтверждает правило. Имхо, не столь очевидное поведение.
 
T

][tiger

Код:
using System;
using System.Collections;

public class MyClass
{
private static ObjectWithEvent _objWithEvent = new ObjectWithEvent();

public static void Main()
{
_objWithEvent.Event += new EventHandler(ObjEventHandler);
_objWithEvent = null;

WL("Initiating garbage collection");
GC.Collect();
WL("GC.Collect finished");

RL();
}

private static void ObjEventHandler(object sender, EventArgs e)
{
//do nothing
}

public static void WL(string text, params object[] args)
{
Console.WriteLine(text, args);	
}

private static void RL()
{
Console.ReadLine();	
}

private static void Break() 
{
System.Diagnostics.Debugger.Break();
}
}

public class ObjectWithEvent
{
public event EventHandler Event;	

~ObjectWithEvent()
{
MyClass.WL("I've been collected");
}
}

Результат:

Initiating garbage collection
I've been collected
GC.Collect finished
 
K

karlito

Поправлю немного. После GC.Collect() необходимо вставить GC.WaitForPendingFinalizers(). Тогда результат во всех случаях будет как ты написал.

Ну и сам уже отвечу Если ссылок больше нет, то GC соберет этот объект и без отписки от событий. Ведь на самом деле, это сам объект ссылается на делегат.... Однако, для коллекции все-таки нужно отписаться...
Вот это я не понял.

Понятно что можно и не отписываться от событий. Но это плохая практика. Допустим на этот объект ссылка имеется в другом месте, а ты вызываешь GC.Collect() и думаешь, что объект удалён из памяти и твой метод, который вызывается по событию, больше вызываться не будет. И в одно прекрасное утро он вызовется и ты этого не ждал, и приложение упало, и пользователи заволновались... :(
 
Статус
Закрыто для дальнейших ответов.
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!