Безопасно ли создавать и использовать одноразовый объект inline?

17

Я видел так много разработчиков, которые использовали одноразовый объект inline, здесь . По встроенным я имею в виду:

var result = new DataTable().Compute("1 + 4 * 7", null);

Я знаю, что метод Dispose не будет вызываться, но поскольку ссылка на объект не указана, как будет обрабатываться сборщик мусора? Безопасно ли использовать одноразовый объект?

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

    
задан Fabien PERRONNET 23.04.2016 в 23:11
источник
  • Хотя это не отвечает на ваш общий вопрос, он говорит со своим примером stackoverflow.com/questions/913228/... –  hatchet 23.04.2016 в 23:16
  • Этот фрагмент был написан умным программистом, который знал, что DataTable не имеет ничего доступного и фактически не реализует Dispose (). Многие программисты .NET очень неудобны в этом. Так что просто не делайте этого, он не становится намного уродливым, когда вы используете оператор using. Вы можете чувствовать себя хорошо, когда никогда не ошибаетесь. –  Hans Passant 24.04.2016 в 00:11

3 ответа

11

Ключевой проблемой здесь является время, когда вызывается Dispose , что просто неизвестно в вашем примере (обеспечивая хорошую реализацию IDisposable - см. ниже). Я бы предпочел использовать экземпляр IDisposable без выражения using запаха кода. Класс использует IDisposable по какой-либо причине, и поэтому вы, как пользователь, должны подчиняться своему контракту.

Однако обратите внимание, что в правильной реализации IDisposable финализатор класса управляет удалением объекта, который не расположен. Следовательно, даже если не , созданный внутри using , удаление должно выполняться, но в неизвестном времени и в другом (GC) потоке.

  

Я просто хотел знать, если они будут обрабатываться с помощью GC, если они используются таким образом.

Нет, GC обрабатывает все объекты одинаково и не обрабатывает IDisposable реализации иначе или иначе. Однако при правильной реализации IDisposable метода Finalize (вызывается GC на каждом объекте, если он не был подавлен для каждого объекта), вызов вызовет вызов Dispose .

    
ответ дан Ondrej Tucny 23.04.2016 в 23:18
  • Я должен согласиться. Несмотря на то, что существуют некоторые классы, где относительно безвредно явно не распоряжаться, это кажется очень плохой привычкой развиваться. –  hatchet 23.04.2016 в 23:24
1

Если объект, который инициализируется inline, имеет реализованный деструктор, этот деструктор может вызвать Dispose () после того, как объект вышел из области видимости.

Однако, более чистый и правильный способ - использовать оператор using, потому что это потенциально может привести к простому обходу объектов без каких-либо целей.     

ответ дан Dmitry K. 23.04.2016 в 23:17
  • Объекты C # не имеют деструкторов. У них могут быть финализаторы. Финализаторы не запускаются, когда объекты выходят за рамки. Они работают, когда GC думает, что пришло время их запускать. –  GSerg 23.04.2016 в 23:20
  • Вы издеваетесь? msdn.microsoft.com/en-us/library/66x5fx1b.aspx –  Dmitry K. 23.04.2016 в 23:21
  • Из вашей ссылки: «Программист не имеет контроля над вызовом деструктора, потому что это определяется сборщиком мусора» –  Poul Bak 23.04.2016 в 23:25
  • Следует также отметить, что если класс имеет финализатор (деструктор в терминологии C #), сборщик мусора не будет собирать этот экземпляр немедленно, в следующем поколении-0 собирать. Вместо этого он добавит экземпляр в очередь финализатора и не завершит сбор этого экземпляра до сбора следующего поколения-1. Поэтому в зависимости от финализатора (деструктора), даже если вы знаете, что он существует и правильно реализован, может привести к поражению производительности. Кроме того, как говорили другие, лучше всего освободить эти ресурсы сейчас, а не ждать появления возможных сборок мусора. –  Jeppe Stig Nielsen 24.04.2016 в 01:06
  • @ruakh Хороший вопрос! Я думаю, что я предполагал, что метод Dispose () называется GC.SuppressFinalize (this). Всякий раз, когда существует деструктор, это должно быть так. В этом случае вызов Dispose () обеспечит немедленный сбор и отсутствие очереди на завершение. Если финализация не подавляется явно так, вы абсолютно правы: хит производительности есть в любом случае. Люди часто удивляются тому, что простое существование деструктора, даже одного с пустым телом, болит в производительности. –  Jeppe Stig Nielsen 24.04.2016 в 09:07
Показать остальные комментарии
1

Небезопасно использовать одноразовые объекты таким образом. Да, ссылка не будет использоваться, но цель одноразового шаблона - распоряжаться всеми неуправляемыми ресурсами (такими как дескрипторы ОС), которые не могут быть собраны в мусор.     

ответ дан Yevgeniy.Chernobrivets 23.04.2016 в 23:18
  • Неуправляемые ресурсы будут выпущены во время сбора мусора, если ранее не были удалены явным вызовом IDisposable.Dispose (). Конечно, это предполагает, что IDisposable выполняется правильно и что финализатор освобождает неуправляемый ресурс. Поэтому на самом деле «безопасно» не удалять одноразовый объект, когда он больше не используется, и оставить его сборщику мусора для его очистки. Однако он не очень умный или эффективный. –  Martin Liversage 24.04.2016 в 01:04