Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: Алексей (IdeaSoft) от 08-09-2016, 23:56:36

Название: Анализатор кода VB NET сообщает "не ликвидировать объекты несколько раз..."
Отправлено: Алексей (IdeaSoft) от 08-09-2016, 23:56:36
Прогнал анализатор кода для проекта VB NET (MS VS 2012 pro) (Autocad 2012 64x)
Анализатор для одного из мест в моем коде выдает следующее:

CA2202   Не ликвидировать объекты несколько раз   Объект "'btr.GetEnumerator()'"
можно удалять более одного раза в методе 'MY_TEST()'. Чтобы избежать исключения
System.ObjectDisposedException, следует вызывать метод "Dispose" для объекта только один раз.

Если комментирую цикл "For Each id As CAD_DBS.ObjectId In btr ... Next ",
то анализатору не сообщает о предупреждении.

1) Что не так делаю?
2) В чем не верна моя конструкция алгоритма?
3) Для какого объекта нужен Dispose?

Алгоритм тестировал - он изменяет объекты и успешно сохраняет файл dwg.
А вот анализатор -ругается!

Код моего метода "MY_TEST"

Код - vb.net [Выбрать]
  1. Imports CAD_DBS = Autodesk.AutoCAD.DatabaseServices
  2. Public sub MY_TEST(byval FileName as String)
  3.             Dim db As CAD_DBS.Database = FUNC_OPEN_DATABASE(FileName)
  4.             If (db IsNot Nothing) Then
  5.                  Using tr As CAD_DBS.Transaction = db.TransactionManager.StartTransaction
  6.                     Dim bt As CAD_DBS.BlockTable = tr.GetObject(db.BlockTableId, CAD_DBS.OpenMode.ForWrite)
  7.                     Dim btr As CAD_DBS.BlockTableRecord = tr.GetObject(bt(CAD_DBS.BlockTableRecord.ModelSpace), CAD_DBS.OpenMode.ForWrite)
  8.                     For Each id As CAD_DBS.ObjectId In btr
  9.                          Dim Ent As CAD_DBS.DBObject = tr.GetObject(id, CAD_DBS.OpenMode.ForWrite)
  10.                          ' что-то делаю с объектом Ent
  11.                     Next
  12.                     tr.Commit()
  13.                 End Using
  14.                 db.CloseInput(True)
  15.                 db.SaveAs(Fn, CAD_DBS.DwgVersion.Current) ' 2016.05.19
  16.                 db.Dispose()
  17.             End If
  18. End Sub
  19.  
  20. Public Function FUNC_OPEN_DATABASE(byval Fn As String) As CAD_DBS.Database
  21.         Dim db As CAD_DBS.Database = Nothing
  22.         Try
  23.             db = New CAD_DBS.Database
  24.         Catch ex As Exception
  25.             Return Nothing
  26.         End Try
  27.         Try
  28.             db.ReadDwgFile(Fn, IO.FileShare.ReadWrite, False, Nothing)
  29.             Return db
  30.         Catch ex As System.Exception
  31.             MsgBox("Не могу прочитать базу чертежа " & vbCrLf & Fn & ex.Message)
  32.             db.Dispose()
  33.             Return Nothing
  34.         End Try
  35. End Function
Название: Re: Анализатор кода VB NET сообщает "не ликвидировать объекты несколько раз..."
Отправлено: Александр Ривилис от 09-09-2016, 00:07:31
У тебя какая-то ошибка при выполнении этого кода? Если нет, то не думаю, что следует обращать внимание.
Анализатор даёт такое сообщение на код, который ты здесь выложил или под комментарием
Код - vb.net [Выбрать]
  1. ' к примеру, что-то буду делать с объектом Ent
скрывается какой-то код, в котором возможно и есть ошибка? Например, что-то типа btr.Dispose() - в этом случае эта ругань была бы уместна.
Бросается в глаза то, что ты открываешь db.BlockTableId на запись, но нигде этим не пользуешься. А следовательно следовало открывать на чтение.
Аналогично и с ModelSpace - если ты его не трогаешь, то никогда не открывай на запись.
3) Для какого объекта нужен Dispose?
Наоборот, анализатор говорит, что ты делаешь лишний Dispose.
Название: Re: Анализатор кода VB NET сообщает "не ликвидировать объекты несколько раз..."
Отправлено: Алексей (IdeaSoft) от 09-09-2016, 00:19:50
что ты открываешь db.BlockTableId на запись, но нигде этим не пользуешься
Ну к примеру в тело цикла я вставил код по которому устанавливаю цвет примитиву
И тоже анализатор ругается.
код тела цикла For Each ... Next
                       
Код - vb.net [Выбрать]
  1. Dim Ent As CAD_DBS.DBObject = tr.GetObject(id, CAD_DBS.OpenMode.ForWrite)
  2.                         DirectCast(Ent, CAD_DBS.Entity).ColorIndex = 7

теперь я уже что-то делаю с объектом  ;)
Название: Re: Анализатор кода VB NET сообщает "не ликвидировать объекты несколько раз..."
Отправлено: Алексей (IdeaSoft) от 09-09-2016, 00:22:44
Аналогично и с ModelSpace - если ты его не трогаешь, то никогда не открывай на запись.
А вот объект
Код - vb.net [Выбрать]
  1. Dim bt As CAD_DBS.BlockTable
открывать на запись или на чтение?
Название: Re: Анализатор кода VB NET сообщает "не ликвидировать объекты несколько раз..."
Отправлено: Александр Ривилис от 09-09-2016, 00:29:22
открывать на запись или на чтение?
Еще раз повторяю: если ты не модифицируешь объект, то открывай его на чтение. В твоём коде не модифицируется ни таблица блоков, ни пространство модели. Если изменился примитив в пространстве модели, то это не значит, что изменилось само пространство модели. Пространство модели изменяется если к нему добавляют примитив. Таблица блоков меняется если к ней добавляется новое описание блока (BlockTableRecord), но не меняется если меняется что-то в самом описанием блока.
Так понятнее?
Название: Re: Анализатор кода VB NET сообщает "не ликвидировать объекты несколько раз..."
Отправлено: Алексей (IdeaSoft) от 09-09-2016, 00:41:10
Так понятнее?
Теперь понял, спасибо!
Значит таблицу "примитивов" вообще нужно открывать "на чтение",  в том случае если я не буду добавлять новых примитивов.
Что интересно еще
я написал цикл через While и анализатор убрал это предупреждение
Код - vb.net [Выбрать]
  1. btr.GetEnumerator.Reset()
  2. Do While btr.GetEnumerator.MoveNext
  3. Dim id As CAD_DBS.ObjectId = btr.GetEnumerator.Current
  4. Dim Ent As CAD_DBS.DBObject = tr.GetObject(id, CAD_DBS.OpenMode.ForWrite)
  5. DirectCast(Ent, CAD_DBS.Entity).ColorIndex = 7
  6. Loop
Может анализатору не нравится For Each..Next?

 
Название: Re: Анализатор кода VB NET сообщает "не ликвидировать объекты несколько раз..."
Отправлено: Александр Ривилис от 09-09-2016, 01:51:22
Может анализатору не нравится For Each..Next?
Может. Думаю, что он просто недостаточно интеллектуальный, чтобы понять этот цикл. :) Советую не обращать внимания.
Название: Re: Анализатор кода VB NET сообщает "не ликвидировать объекты несколько раз..."
Отправлено: Александр Ривилис от 09-09-2016, 01:52:02
Значит таблицу "примитивов" вообще нужно открывать "на чтение",  в том случае если я не буду добавлять новых примитивов.
Именно!
Название: Re: Анализатор кода VB NET сообщает "не ликвидировать объекты несколько раз..."
Отправлено: Алексей (IdeaSoft) от 09-09-2016, 08:32:07
что он просто недостаточно интеллектуальный
У была такая догадка, что это недоработка самого анализатора MS VB.
Есть еще некоторые места в моем коде где я использую конструкцию
For Each ... Next где я не использую функции AutoCAD API.