Не работает свойство PromptSelectionOptions.RejectObjectsFromNonCurrentSpace

Автор Тема: Не работает свойство PromptSelectionOptions.RejectObjectsFromNonCurrentSpace  (Прочитано 12145 раз)

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

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Доброго времени суток.

- AutoCAD 2009 x64 SP3 Enu
- AutoCAD 2014 x64 SP1 Enu

Сотрудники расчётного отдела нашей компании обратились ко мне с маленькой просьбой: написать команду, которая в текущем пространстве (Model\Layout) будет выбирать все полилинии, которые имеют заданное количество вершин. Задачка простая, однако в ходе её решения натолкнулся на неприятный баг: свойство PromptSelectionOptions.RejectObjectsFromNonCurrentSpace не работает. Тестировал в указанных выше версиях AutoCAD.

Код - C# [Выбрать]
  1. // SpaceEnum.cs
  2. // © Andrey Bushman, 2013
  3.  
  4. namespace Bushman.CAD.DatabaseServices {
  5.         /// <summary>
  6.         /// This enum indicates the current space in the current Database.
  7.         /// </summary>
  8.         public enum SpaceEnum {
  9.                 /// <summary>
  10.                 /// The Model space.
  11.                 /// </summary>
  12.                 Model,
  13.                 /// <summary>
  14.                 /// The Layout space.
  15.                 /// </summary>
  16.                 Layout,
  17.                 /// <summary>
  18.                 /// The Model space through the Layout's viewport.
  19.                 /// </summary>
  20.                 Viewport
  21.         }
  22. }

Код - C# [Выбрать]
  1. // LayoutManagerExtensionMethods.cs
  2. // © Andrey Bushman, 2013
  3.  
  4. //Microsoft
  5. using System;
  6.  
  7. //Autodesk
  8. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  9. using App = Autodesk.AutoCAD.ApplicationServices;
  10. using Db = Autodesk.AutoCAD.DatabaseServices;
  11. using Ed = Autodesk.AutoCAD.EditorInput;
  12.  
  13. namespace Bushman.CAD.DatabaseServices {
  14.  
  15.         public static class LayoutManagerExtensionMethods {
  16.                 /// <summary>
  17.                 /// This is Extension Method for the <c>Autodesk.AutoCAD.DatabaseServices.LayoutManager</c>
  18.                 /// class. It gets the current space in the current Database.
  19.                 /// </summary>
  20.                 /// <param name="mng">Target <c>Autodesk.AutoCAD.DatabaseServices.LayoutManager</c>
  21.                 /// instance.</param>
  22.                 /// <returns>Returns the SpaceEnum value.</returns>            
  23.                 public static SpaceEnum GetCurrentSpaceEnum(this Db.LayoutManager mng) {
  24.                         Db.Database db = cad.DocumentManager.MdiActiveDocument.Database;
  25.                         Int16 tilemode = (Int16)cad.GetSystemVariable("TILEMODE");
  26.  
  27.                         if (tilemode == 1)
  28.                                 return SpaceEnum.Model;
  29.  
  30.                         Int16 cvport = (Int16)cad.GetSystemVariable("CVPORT");
  31.                         if (cvport == 1)
  32.                                 return SpaceEnum.Layout;
  33.                         else
  34.                                 return SpaceEnum.Viewport;
  35.                 }
  36.  
  37.                 /// <summary>
  38.                 /// This is Extension Method for the <c>Autodesk.AutoCAD.DatabaseServices.LayoutManager</c>
  39.                 /// class. It gets the name of the current space in the current Database.
  40.                 /// </summary>
  41.                 /// <param name="mng">Target <c>Autodesk.AutoCAD.DatabaseServices.LayoutManager</c>
  42.                 /// instance.</param>
  43.                 /// <returns>Returns the name of current space.</returns>
  44.                 public static String GetCurrentSpaceName(this Db.LayoutManager mng) {
  45.                         SpaceEnum space = GetCurrentSpaceEnum(mng);
  46.                         Db.Database db = cad.DocumentManager.MdiActiveDocument.Database;
  47.                         String modelSpaceLocalizedName = String.Empty;
  48.                         using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {
  49.                                 Db.BlockTable bt = tr.GetObject(db.BlockTableId, Db.OpenMode.ForRead) as Db.BlockTable;
  50.                                 Db.BlockTableRecord btr = tr.GetObject(bt[Db.BlockTableRecord.ModelSpace], Db.OpenMode.ForRead)
  51.                                         as Db.BlockTableRecord;
  52.                                 modelSpaceLocalizedName = (tr.GetObject(btr.LayoutId, Db.OpenMode.ForRead) as Db.Layout).LayoutName;
  53.                         }
  54.                         String result = space == SpaceEnum.Viewport ?
  55.                                 "Model" as String : mng.CurrentLayout;
  56.                         return result;
  57.                 }
  58.  
  59.                 /// <summary>
  60.                 /// This is Extension Method for the <c>Autodesk.AutoCAD.DatabaseServices.LayoutManager</c>
  61.                 /// class. It gets the localized name of the Model tab.
  62.                 /// </summary>
  63.                 /// <param name="mng">Target <c>Autodesk.AutoCAD.DatabaseServices.LayoutManager</c>
  64.                 /// instance.</param>
  65.                 /// <returns>Returns the name of current space.</returns>
  66.                 public static String GetModelTabLocalizedName(this Db.LayoutManager mng) {
  67.                         Db.Database db = cad.DocumentManager.MdiActiveDocument.Database;
  68.                         String modelTabLocalizedName = String.Empty;
  69.                         using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {
  70.                                 Db.BlockTable bt = tr.GetObject(db.BlockTableId, Db.OpenMode.ForRead) as Db.BlockTable;
  71.                                 Db.BlockTableRecord btr = tr.GetObject(bt[Db.BlockTableRecord.ModelSpace], Db.OpenMode.ForRead)
  72.                                         as Db.BlockTableRecord;
  73.                                 modelTabLocalizedName = (tr.GetObject(btr.LayoutId, Db.OpenMode.ForRead) as Db.Layout).LayoutName;
  74.                         }
  75.                         return modelTabLocalizedName;
  76.                 }
  77.         }
  78. }

Код - C# [Выбрать]
  1. // SelectionCommands.cs
  2. // Выбор всех полилиний с указанным количеством вершин. © Andrey Bushman, 2013
  3. // Заказ сотрудников расчётного отдела нашей компании.
  4.  
  5. #define SECOND_VARIANT
  6.  
  7. //Microsoft
  8. using System;
  9.  
  10. //Autodesk
  11. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  12. using App = Autodesk.AutoCAD.ApplicationServices;
  13. using Db = Autodesk.AutoCAD.DatabaseServices;
  14. using Ed = Autodesk.AutoCAD.EditorInput;
  15. using Rtm = Autodesk.AutoCAD.Runtime;
  16.  
  17. // Bushman
  18. using Bushman.CAD.DatabaseServices;
  19.  
  20. [assembly: Rtm.ExtensionApplication(typeof(Bushman.CAD.Commands.SelectionCommands))]
  21. [assembly: Rtm.CommandClass(typeof(Bushman.CAD.Commands.SelectionCommands))]
  22.  
  23. namespace Bushman.CAD.Commands {
  24.  
  25.         public sealed class SelectionCommands : Rtm.IExtensionApplication {
  26.  
  27.                 [Rtm.CommandMethod("PlineSel", Rtm.CommandFlags.Modal)]
  28.                 public void PolylineSelectionViaVertexCount() {
  29.                         App.Document doc = cad.DocumentManager.MdiActiveDocument;
  30.                         Db.Database db = doc.Database;
  31.                         Ed.Editor ed = doc.Editor;
  32.  
  33.                         Ed.PromptIntegerOptions intOpt = new Ed.PromptIntegerOptions("\nКоличество вершин в полилиниях, подлежащих выборке");
  34.                         intOpt.AllowNegative = false;
  35.                         intOpt.AllowNone = false;
  36.                         intOpt.AllowZero = false;
  37.  
  38.                         Ed.PromptIntegerResult intRes = ed.GetInteger(intOpt);
  39.  
  40.                         if (intRes.Status != Ed.PromptStatus.OK) {
  41.                                 ed.WriteMessage("\nНе было выбрано ни одного примитива.\n");
  42.                                 return;
  43.                         }
  44.  
  45. #if !SECOND_VARIANT
  46.                         Boolean rejectObjectsFromNonCurrentSpace = true;
  47.                         Db.TypedValue[] filterList = new Db.TypedValue[2];                     
  48. #else
  49.                         Db.TypedValue[] filterList = new Db.TypedValue[3];
  50.  
  51.                         Db.LayoutManager layMng = Db.LayoutManager.Current;
  52.                         String curLayoutName = layMng.GetCurrentSpaceName();
  53.  
  54.                         filterList[2] = new Db.TypedValue(410, curLayoutName);
  55. #endif
  56.                         filterList[0] = new Db.TypedValue((Int32)Db.DxfCode.Start, "LWPOLYLINE");
  57.                         filterList[1] = new Db.TypedValue(90, intRes.Value);
  58.  
  59.                         Ed.SelectionFilter filter = new Ed.SelectionFilter(filterList);
  60.                         Ed.PromptSelectionOptions selOpt = new Ed.PromptSelectionOptions();
  61.                         selOpt.SingleOnly = false;
  62.  
  63. #if !SECOND_VARIANT
  64.                         selOpt.RejectObjectsFromNonCurrentSpace = rejectObjectsFromNonCurrentSpace;
  65. #endif
  66.  
  67.                         // Нужно в текущем пространстве (Модель\Лист) выделить все примитивы согласно фильтру
  68.                         // так, чтобы отображались в т. ч. и ручки. Причём указанное выделение должно оставаться
  69.                         // активным и по завершению работы кода
  70.                         Ed.PromptSelectionResult selRes = ed.SelectAll(filter);
  71.  
  72.                         if (selRes.Status != Ed.PromptStatus.OK) {
  73.                                 ed.WriteMessage("\nНе было выбрано ни одного примитива.\n");
  74.                                 return;
  75.                         }
  76.  
  77.                         ed.WriteMessage("\nКоличество выбранных примитивов: {0}\n", selRes.Value.Count);
  78.  
  79.                         // Результаты выборки подсвечиваю с отображением "ручек":
  80.                         ed.SetImpliedSelection(selRes.Value.GetObjectIds());
  81.  
  82.                         // Если нужно просто подсветить объекты, без отображения "ручек" то следует
  83.                         // использовать Entity.Highlight(). Чтобы снять такую подсветку, нужно вызывать
  84.                         // метод Entity.Unhighlight()
  85.  
  86.                         // Чтобы очистить текущий набор выборки следует поступать так:
  87.                         // ed.SetImpliedSelection(new Db.ObjectId[0]);
  88.                 }
  89.  
  90.                 #region IExtensionApplication Members
  91.  
  92.                 public void Initialize() {
  93.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  94.                         ed.WriteMessage("\nPlineSel. © Andrey Bushman, 2013\n");
  95.                 }
  96.  
  97.                 public void Terminate() {
  98.                         // throw new NotImplementedException();
  99.                 }
  100.  
  101.                 #endregion
  102.         }
  103. }

К сообщению я прикрепляю чертёж, на котором тестировал код. В пространстве Model находится несколько полилиний, в том числе четыре из них имеют четыре вершины. В пространстве Layout находится ещё две полилинии с четырьмя вершинами.

В выше приведённом коде я показываю два способа фильтрации искомого контента (в файле SelectionCommands.cs обратите внимание на строку 5 и блоки кода в строках 45-55 и 63-65).

Если в обозначенном выше чертеже, находясь в Model или в Layout (в данном случае это не важно), запустить команду PlineSel и в качестве количества вершин указать 4, то в консоли AutoCAD получаем такой результат:

Цитата: AutoCAD Console
Command: PLINESEL
Количество вершин в полилиниях, подлежащих выборке: 4
Количество выбранных элементов: 6

Как видим, в выборку попадают и те полилинии, которые находятся в Layout. И это несмотря на то, что PromptSelectionOptions.RejectObjectsFromNonCurrentSpace установлено в true.

Т. о. получаемый результат неверен.

Для того, чтобы обойти обозначенную выше проблему, раскомментируем в коде строку 5. Теперь в фильтр будет добавлена дополнительная запись с кодом 410. В этом случае я получаю корректные результаты:

Для Model:
Цитата: AutoCAD Console
Command: PLINESEL
Количество вершин в полилиниях, подлежащих выборке: 4
Количество выбранных элементов: 4

Для Layout:
Цитата: AutoCAD Console
Command: PLINESEL
Количество вершин в полилиниях, подлежащих выборке: 4
Количество выбранных элементов: 2

Пользуясь случаем хочу передать привет группе тестирования AutoCAD (ходят слухи, что они всё таки существуют, хотя то же самое, порой, говорят и о Деде Морозе...  ;) ). Желаю этим отличным парням хорошо встретить и провести Новый Год! Того же самого желаю и тем программистам Autodesk, которые много лет назад (как минимум шесть) написали код свойства  PromptSelectionOptions.RejectObjectsFromNonCurrentSpace но поленились проверить его работоспособность. Счастливого вам Нового Года, товарищи программисты! Не икайте там и не кашляйте...
« Последнее редактирование: 24-12-2013, 17:15:33 от Андрей Бушман »

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Может я по диагонали посмотрел - а с чего он (PromptSelectionOptions) должен учитываться в SelectAll(...) ?? Ну создали Вы его с соответствующими опциями - он же ни в каком виде методу не передается и насколько я понимаю служит для передачи методу Editor.GetSelection(...) - которого в Вашем коде я не нашел.
« Последнее редактирование: 24-12-2013, 17:23:28 от Александр Ривилис »

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Вообще-то чтобы после команды выбранные ручки остались подсвеченными нужно чтобы у команды был флаг CommandFlags.Redraw, а чтобы команда могла использовать предварительный выбор еще и CommandFlags.UsePickSet
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Может я по диагонали посмотрел - а с чего он (PromptSelectionOptions) должен учитываться в SelectAll(...)

5 баллов! И я это просмотрел! Хорошо что не успел отправить в ADN DevHelp - пришлось бы краснеть...

Пользуясь случаем хочу передать привет группе тестирования AutoCAD (ходят слухи, что они всё таки существуют, хотя то же самое, порой, говорят и о Деде Морозе...  ;) ).
Андрей. Эта группа не тестирует AutoCAD API. Они тестируют (в меру своих возможностей) сам AutoCAD. Среди них нет программистов - тестировщики это совершенно отдельная профессия.
« Последнее редактирование: 24-12-2013, 15:47:33 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Может я по диагонали посмотрел - а с чего он (PromptSelectionOptions) должен учитываться в SelectAll(...) ?? Ну создали Вы его с соответствующими опциями - он же ни в каком виде методу не передается и насколько я понимаю служит для передачи методу Editor.GetSelection(...) - которого в Вашем коде я не нашел.
А млин... :) Точно, слона-то я и не заметил. Дело в том, что изначально у меня в коде был не SelectAll, а GetSelection, дабы юзер сам указывал интересующий его диапазон. Но попробовав, юзеры попросили, чтобы выборка автоматом производилась по всему текущему пространству...

Я выборку поменять-то поменял на SelectAll, но прозевал, что после этого PromptSelectionOptions конечно же становится не использованым и, как следствие, вовсе не нужен... :)

Спасибо.

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Вообще-то чтобы после команды выбранные ручки остались подсвеченными нужно чтобы у команды был флаг CommandFlags.Redraw, а чтобы команда могла использовать предварительный выбор еще и CommandFlags.UsePickSet
Про UsePickSet я помню, но в данной задаче он не нужен. Обозначенный мною выше код подсвечивает ручки и без Redraw, проверял в:
- AutoCAD 2014 SP1 x64 Enu
- AutoCAD 2009 SP3 x64 Enu
- AutoCAD 2009 SP3 x86 Enu

Хотя я конечно же добавлю обозначенный, Вами флаг, спасибо.
« Последнее редактирование: 24-12-2013, 16:24:22 от Андрей Бушман »

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Вообще-то чтобы после команды выбранные ручки остались подсвеченными нужно чтобы у команды был флаг CommandFlags.Redraw, а чтобы команда могла использовать предварительный выбор еще и CommandFlags.UsePickSet
Практика показывает, что Redraw - это для того, чтобы ручки остались подсвеченными после завершения работы программы, только если нужно обрабатывать предварительный выбор. То есть, при наличии Redraw, UsePickSet не нужен. Сам недавно узнал от тов. bargool с dwg.ru.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Практика конечно же критерий истины, но лучше всё-таки указывать флаги так, как это полагается делать. Кстати в ObjectARX без этих флагов набор предварительного выбора не подсвечивается/создаётся. И так было всегда! Так что и в AutoCAD .NET API в очередной версии может перестать работать, ибо в принципе это "недокументированное поведение", а по-русски - баг!
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Так что и в AutoCAD .NET API в очередной версии может перестать работать, ибо в принципе это "недокументированное поведение", а по-русски - баг!
На протяжении как минимум шести лет, ибо наблюдается как в 2009-м, так и в 2014-м. Интуитивно ожидаю аналогичного поведения и в 2015-м. Данный случай, конечно не смертелен, но всё же хотелось бы соответствия тому поведению, которое наблюдается в "родном" ARX.

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Поскольку пользователям потребовалось выбирать не только экземпляры Polyline, но и Polyline2d, Polyline3d, то возможность использования SelectionFilter отпадает. Однако в AutoCAD можно реализовать и свой собственный механизм фильтрации, на мой взгляд подчас более гибкий чем тот, который в AutoCAD имеется по умолчанию. Пример одной альтернативной реализации можно посмотреть здесь (механизм реализован в виде набора методов расширений и базируется на технологии LINQ).

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
>>возможность использования SelectionFilter отпадает.
*line - выберет все типы + просто линии, а также есть еще маркеры логических гупп "<or" "or>" "<and" "and>" и пр.
p.s. Ихмо для таких задач лисп рулит - строчки 4 наверное получится...
p.p.s. а про вершины забыл - да фильтровать еще все равно придется...

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
>>возможность использования SelectionFilter отпадает.
*line - выберет все типы + просто линии, а также есть еще маркеры логических гупп "<or" "or>" "<and" "and>" и пр.
p.s. Ихмо для таких задач лисп рулит - строчки 4 наверное получится...
Дима. А вот в этот раз ты прочитал вопрос по диагонали.  ;) Только у LWPOLYLINE есть свойство в dxf-группе отвечающее за количество вершин. POLYLINE такого свойства не имеет и даже "не знает" сколько у неё вершин.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
>>возможность использования SelectionFilter отпадает.
*line - выберет все типы + просто линии, а также есть еще маркеры логических гупп "<or" "or>" "<and" "and>" и пр.
p.s. Ихмо для таких задач лисп рулит - строчки 4 наверное получится...
Я с интересом посмотрел бы, как у Вас это получится... :)

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
да стормозил - с телефона пишу - пока понял уже 2 поста добавилось.
p.s. задача резко возрастает до 7-8 строчек :-)

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
POLYLINE такого свойства не имеет и даже "не знает" сколько у неё вершин.

Это дело поправимое...

Код - C# [Выбрать]
  1. // PolylineExtensionMethods.cs. © Andrey Bushman, 2013
  2.  
  3. // Microsoft
  4. using System;
  5. using System.Collections;
  6.  
  7. //Autodesk
  8. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  9. using App = Autodesk.AutoCAD.ApplicationServices;
  10. using Db = Autodesk.AutoCAD.DatabaseServices;
  11. using Ed = Autodesk.AutoCAD.EditorInput;
  12. using Rtm = Autodesk.AutoCAD.Runtime;
  13.  
  14.  
  15. namespace Bushman.CAD.Tests {
  16.  
  17.         /// <summary>
  18.         /// Extension methods for the Polyline2d and Polyline3d instances.
  19.         /// </summary>
  20.         public static class PolylineExtensionMethods {
  21.  
  22.                 /// <summary>
  23.                 /// Get the number of vertices in the Polyline2d instance.
  24.                 /// </summary>
  25.                 /// <param name="polyline">Target Polyline2d instance.</param>
  26.                 /// <returns>The number of vertices in the Polyline2d instance.</returns>
  27.                 public static Int32 GetNumberOfVertices(this Db.Polyline2d polyline) {
  28.                         return GetItemsCount(polyline);
  29.                 }
  30.  
  31.                 /// <summary>
  32.                 /// Get the number of vertices in the Polyline3d instance.
  33.                 /// </summary>
  34.                 /// <param name="polyline">Target Polyline3d instance.</param>
  35.                 /// <returns>The number of vertices in the Polyline3d instance.</returns>
  36.                 public static Int32 GetNumberOfVertices(this Db.Polyline3d polyline) {
  37.                         return GetItemsCount(polyline);
  38.                 }
  39.  
  40.                 /// <summary>
  41.                 /// Get the items count for the IEnumerable instance.
  42.                 /// </summary>
  43.                 /// <param name="en">Target IEnumerable instance.</param>
  44.                 /// <returns>The items count.</returns>
  45.                 static Int32 GetItemsCount(IEnumerable en) {
  46.                         Int32 count = 0;
  47.                         foreach (var item in en) {
  48.                                 ++count;
  49.                         }
  50.                         return count;
  51.                 }
  52.         }
  53. }

Теперь "знает" :).

Пример использования:

Код - C# [Выбрать]
  1. Db.Polyline2d poly2d = null;
  2. Db.Polyline3d poly3d = null;
  3.  
  4. // here is some initializing of poly2d and poly3d
  5. // ...
  6.  
  7. Int32 count2d = poly2d.GetNumberOfVertices();
  8. Int32 count3d = poly3d.GetNumberOfVertices();
  9.  

Как-то так :).