Короткий ответ, нет, o
будет освобожден. Не беспокойтесь об этом.
Слегка развернутый ответ:
Вашего код делает более или менее следующее:
- Создать некоторое локальное хранилище на эту тему для ссылки на новый MyClass (
o
).
- Создать новый MyClass
- Сохраните ссылку на новый MyClass по адресу
o
.
- Создайте нового делегата из лямбда.
- Назначить делегату событие (
o
теперь имеет ссылку на делегата).
В любой момент времени GC может останавливать потоки, а затем проверять, какие объекты являются или нет. Корни являются объектами, которые являются статическими или в локальном хранилище потока (под которым я подразумеваю локальные переменные в выполнении данного потока, реализуемые стеком, а не «Thread-Local Storage», который по существу является формой статического). Корневыми объектами являются корни, объекты, на которые они ссылаются, объекты, на которые ссылаются те, и т. Д. Корневые объекты не будут собраны, остальное будет (за исключением некоторых дополнительных вещей, которые нужно сделать с финализаторами, которые мы сейчас будем игнорировать).
Ни в коем случае после создания объекта MyClass он не был укоренен локальным хранилищем потока.
Ни при каких обстоятельствах после создания объекта-делегата он не был укоренен локальным хранилищем потока или MyClass, имеющим ссылку на него.
Теперь, что будет дальше?
Это зависит. Лямбда не сохранит MyClass в живых (MyClass сохраняет его в живых, но когда MyClass идет, также делает лямбда). Этого недостаточно, чтобы ответить: «Будет ли« быть »для сбора мусора здесь?» хоть.
void Meth0()
{
var o = new MyClass();
o.MyClassEvent += (args) => {};
}//o is likely eligible for collection, though it doesn't have to be.
void Meth1()
{
int i = 0;
{
var o = new MyClass();
o.MyClassEvent += (args) => {};
}//o is likely not eligible for collection, though it could be.
while(i > 100000000);//just wasting time
}
void Meth2()
{
{
var o = new MyClass();
o.MyClassEvent += (args) => {};
int i = 0;//o is likely eligible for collection, though it doesn't have to be.
while(i > 100000000);//just wasting time
}
}
void Meth3()
{
{
var o = new MyClass();
o.MyClassEvent += (args) => {};
var x0 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x1 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x2 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x3 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x4 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x5 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x6 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x7 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x8 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x9 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x10 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x11 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
int i = 0;
while(i > 100000000);//just wasting time
}
}
Meth0, по-видимому, самый простой, но на самом деле его нет, поэтому мы вернемся к нему.
В Meth1, реализация вероятно будет оставить локальное хранилище, как это, так как он больше не нужен, так что пока o
не в объеме, реализация будет еще что локальное хранение в использовании.
В Meth2, реализация может использовать то же локальное хранилище он использовал для o
для i
так что даже если он все еще в области видимости, она будет иметь право собирать («в рамках» означает, что программист может выбрать сделать что-то с этим, но он или она этого не сделали, и скомпилированный код не нуждается в такой концепции).
Meth3, скорее всего, повторит использование хранилища, поскольку дополнительные временные его применения делают эту реализацию по сравнению с настройкой в сторону всего хранилища для начала, имеют больше смысла.
Ни одна из этих вещей не имеет. Meth2 и Meth3 могли бы отбросить все хранилища, необходимые для этого метода в начале. Meth1 может повторно использовать хранилище, потому что не имеет никакого значения переупорядочивать i
и o
.
Meth0 более сложный, поскольку он может зависеть от того, что метод вызова делает рядом с локальным хранилищем, а не с очисткой в то время (оба являются законными реализациями). IIRC всегда есть очистка с текущей реализацией, но я не уверен, и это не имеет никакого значения.
В целом, область действия не является релевантной, но может ли компилятор, а затем и JITter использовать и использовать локальное хранилище, связанное с объектом. Можно даже очистить объект до того, как будут вызваны методы и свойства его (если эти методы и свойства не используют this
или любое из полей объекта, потому что он будет работать отлично, если объект был удален!).
Он должен иметь право на GC. Я не уверен в этом, чтобы дать ему ответ. –
Я не понимаю, почему это будет вести себя иначе, чем подписка на любую другую функцию (лямбда или иначе) на событие. Поэтому я согласен с Тимом. –
Возможный дубликат [Сбор мусора при использовании анонимных делегатов для обработки событий] (http://stackoverflow.com/questions/371109/garbage-collection-when-using-anonymous-delegates-for-event-handling) –