Анализатор кода VB NET сообщает "не ликвидировать объекты несколько раз..."

Автор Тема: Анализатор кода VB NET сообщает "не ликвидировать объекты несколько раз..."  (Прочитано 5402 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн Алексей (IdeaSoft)Автор темы

  • ADN
  • *
  • Сообщений: 1188
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
Прогнал анализатор кода для проекта 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

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
У тебя какая-то ошибка при выполнении этого кода? Если нет, то не думаю, что следует обращать внимание.
Анализатор даёт такое сообщение на код, который ты здесь выложил или под комментарием
Код - vb.net [Выбрать]
  1. ' к примеру, что-то буду делать с объектом Ent
скрывается какой-то код, в котором возможно и есть ошибка? Например, что-то типа btr.Dispose() - в этом случае эта ругань была бы уместна.
Бросается в глаза то, что ты открываешь db.BlockTableId на запись, но нигде этим не пользуешься. А следовательно следовало открывать на чтение.
Аналогично и с ModelSpace - если ты его не трогаешь, то никогда не открывай на запись.
3) Для какого объекта нужен Dispose?
Наоборот, анализатор говорит, что ты делаешь лишний Dispose.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей (IdeaSoft)Автор темы

  • ADN
  • *
  • Сообщений: 1188
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
что ты открываешь 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

теперь я уже что-то делаю с объектом  ;)

Оффлайн Алексей (IdeaSoft)Автор темы

  • ADN
  • *
  • Сообщений: 1188
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
Аналогично и с ModelSpace - если ты его не трогаешь, то никогда не открывай на запись.
А вот объект
Код - vb.net [Выбрать]
  1. Dim bt As CAD_DBS.BlockTable
открывать на запись или на чтение?

Отмечено как Решение Алексей (IdeaSoft) 09-09-2016, 01:07:07

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
открывать на запись или на чтение?
Еще раз повторяю: если ты не модифицируешь объект, то открывай его на чтение. В твоём коде не модифицируется ни таблица блоков, ни пространство модели. Если изменился примитив в пространстве модели, то это не значит, что изменилось само пространство модели. Пространство модели изменяется если к нему добавляют примитив. Таблица блоков меняется если к ней добавляется новое описание блока (BlockTableRecord), но не меняется если меняется что-то в самом описанием блока.
Так понятнее?
« Последнее редактирование: 09-09-2016, 01:52:50 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей (IdeaSoft)Автор темы

  • ADN
  • *
  • Сообщений: 1188
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
Так понятнее?
Теперь понял, спасибо!
Значит таблицу "примитивов" вообще нужно открывать "на чтение",  в том случае если я не буду добавлять новых примитивов.
Что интересно еще
я написал цикл через 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?

 

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Может анализатору не нравится For Each..Next?
Может. Думаю, что он просто недостаточно интеллектуальный, чтобы понять этот цикл. :) Советую не обращать внимания.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Значит таблицу "примитивов" вообще нужно открывать "на чтение",  в том случае если я не буду добавлять новых примитивов.
Именно!
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей (IdeaSoft)Автор темы

  • ADN
  • *
  • Сообщений: 1188
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
что он просто недостаточно интеллектуальный
У была такая догадка, что это недоработка самого анализатора MS VB.
Есть еще некоторые места в моем коде где я использую конструкцию
For Each ... Next где я не использую функции AutoCAD API.