Что будет если этого не делать?Скорее всего не будет происходить сборка мусора (не всегда стоит доверять автоматической сборке мусора, так как нет точного понятия, когда она происходит) и не будут освобождаться ресурсы = забивание памяти. Также, можно предположить - если транзакция в автокаде несет туже смысловую нагрузку, что и в базах данных, то возможно там "под капотом" существует что-то типа соединения с БД чертежа, которое закрывается в Dispose()
Что будет если этого не делать? Может быть, это не так уж необходимо?Итак. Если нет вызова Transaction.Commit, и нет Transaction.Dispose, то Transaction.Dispose будет вызван сборщиком мусора. Причем это может произойти в любой момент времени и даже в другом потоке, что вероятно приведет к краху AutoCAD. Напоминаю, что Transaction.Dispose в случае если не вызван Transaction.Commit приводит к Transaction.Abort и откат изменений. Если Transaction.Commit вызывается, то Transaction.Dispose ничего не делает и соответственно всё должно завершится нормально.
А оказывается, что это необязательно.Ну хуже точно не будет. Вообще, есть такое правило "Если объект реализует интерфейс IDisposable, всегда используй using" ))
А оказывается, что это необязательно.Это самая правильная форма записи. В частности при любом exception внутри using будет вызван tr.Dispose. В случае отсутствия using и try/catch/finally ты не можешь быть уверен, что будет вызван tr.Commit(), т.к. исключение может произойти раньше.
Просто источник кода довольно серьёзный.Это может быть и учебный код, когда на такие вещи закрывают глаза, чтобы не потерялся основной алгоритм.
Если объект реализует интерфейс IDisposable, всегда используй usingЭх! Если бы всё было так просто... Иногда следование этому правилу приводит к фатальным ошибкам. Потому что, как потом оказывается, этим объектом управляет какой-то другой внутренний механизм и когда его явно диспозишь, это вызывает крах.
Вообще же tr.Dispose выполняет какие-то действия:Да, я тоже сейчас заглянул в библиотеки. При вызове Dispose() цепочка длинная получается, но в итоге действительно приходим к методу DeleteUnmanagedObject(). К сожалению, что там делается - не понять. Пожалуй, Вы правы - лучше вызывать явно в коде!
Это может быть и учебный код, когда на такие вещи закрывают глаза, чтобы не потерялся основной алгоритм.Это в библиотеках Dynamo для Civil. У них там всё довольно запутано - обёртка на обёртке. Транзакция создаётся и коммитится внутри их библиотек, но почему-то не диспозится.
Это в библиотеках Dynamo для Civil.Ну это тоже не показатель крутизны. :-)
Сейчас вот думаю - может быть по этой причине и выскакивает исключение?Вполне возможно.
Иногда следование этому правилу приводит к фатальным ошибкам.Кто купил книгу Полещука Н.Н. "Программирование для AutoCAD 2013-2015", со страницы 207 об этом хорошо описано.
Это самая правильная форма записи. В частности при любом exception внутри using будет вызван tr.Dispose. В случае отсутствия using и try/catch/finally ты не можешь быть уверен, что будет вызван tr.Commit(), т.к. исключение может произойти раньше.Маленькое уточнение using за программиста оборачивает код в try/catch/finally т.е. это то же самое, только запись короче и читабельнее.
может быть по этой причине и выскакивает исключение?Вполне может быть причиной. Как написали ранее сборщик мусора выполнит Dispose() практически в любом случае, но позже, например при закрытии Civil, когда уже все Database закрыты и из второго потока. Т.е. метод Dispose() Net Wrapper может попытаться обратиться к объекту, которого уже не существует.
Вызывай всегда, кроме случаев, когда объект создавал AutoCAD. Т.е. Document и Database открытые AutoCADом он и должен закрывать.Опять же, очень упрощённая логика. Раз уж разговор изначально про транзакцию, то по этой логике AutoCAD должен её сам закрывать. Мы же не создаём её:
Если ты создал пустую Database то должен закрыть ты.
А создаёт её сам AutoCAD, если точнее - менеджер транзакций:Точнее ты говоришь менеджеру транзакции создать для тебя транзакцию.
Точнее ты говоришь менеджеру транзакции создать для тебя транзакцию.Это в данном случае мы уже по опыту знаем, что мы создаём транзакцию. А если следовать логике названий, то метод не создаёт транзакцию, а запускает. То есть, если бы было название CreateAndStartTransaction или StartNewTransaction, то уже было бы интуитивно понятно, что создаётся новый объект. Мне встречались и другие методы, которые в своём названии не содержат намёков на то, что новый объект создаётся. И даже случаи, когда новый объект создаётся при обращении к свойству! Созданные таким образом объекты нужно было самостоятельно уничтожать. С автокадом нужно всегда держать ухо востро - изучать документацию, лезть внутрь библиотек, проводить тесты. Практика показывает, что даже примерам от ADN и из справки нельзя верить! Они сами иногда не до конца понимают как нужно правильно с объектами автокада работать, пока жаренный петух не клюнет :)
В действительности универсального правила нет.
Так что, тут важно не кто создаёт объект, а область его использования. Если она выходит за рамки кода, то диспозить его не нужно.
Кстати, ещё пример вспомнил. В методе TransformOverrule.Explode можно изменить коллекцию получаемых после взрыва объектов. Для этого мы их создаём (не AutoCAD) и помещаем в выходную коллекцию. Попробуйте их диспозить, следуя логике "из книжки"
Это в данном случае мы уже по опыту знаем, что мы создаём транзакцию. А если следовать логике названий, то метод не создаёт транзакцию, а запускает. То есть, если бы было название CreateAndStartTransaction или StartNewTransaction, то уже было бы интуитивно понятно, что создаётся новый объект.