Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Производительность оператора Is


Автор: amarenkov 25.6.2009, 13:24
Добрый день.

Есть разные классы от одного предка (SomeClass). Внутри функции необходимо определить, какой из этих классов был передан через параметр типа SomeClass.

Вопрос в следующем - что будет производительнее: проверять переданный object при помощи оператора is на соответствие всем этим классам по-очереди, или создать у класса SomeClass поле перечеслимого типа (которое содержало бы "идентификаторы" всех дочерних классов) и проверить это поле через switch?

Вопрос можно переформулировать еще проще - что производительнее: an_object is SomeClass2 или an_object.OurType == OurTypes.SomeClass2?

Заранее спасибо smile.

Автор: DVariuS 25.6.2009, 13:37
amarenkov, быстрее будет конечно-же 
Код

an_object.OurType == OurTypes.SomeClass2

но правильнее все-таки 
Код

an_object is SomeClass2

т.к. более наглядно отображает смысл.
P.S. А еще лучше приведи фрагмент кода, где ты хочешь использовать такую проверку.

Автор: archeg 25.6.2009, 14:06
Это зависит от архитектуры и зачем оно нужно. Например если у тя много класов, то для каждого создавать перечислимое поле - геморно. Тем более информация будет повторяться - уже есть тип класа, то зачем же его еще прописывать в поле?
Но перечисляемые поля имеют свой "+". Где-то можно добавить какую-то гибкость, не усложняя при этом иерархию:
Код

class Number : Symbol
{
    public int Value {get; set;}
    
    public SymbolClassification GetClassification()
    {
         return Value > 0 ? SymbolClassification.PositiveNumber : SymbolClassification.NegetiveOrNullNumber;
    }
}


Добавлено @ 14:08
И вообще помойму is будет быстрее ==. Ток вопрос на самом деле не в скорости, а удобстве. Я надеюсь)

Автор: PashaPash 25.6.2009, 15:08
amarenkov, быстрее - и правильнее - не писать switch или цепочку if-else по типам, а вынести типозависымый код в виртуальные функции. 
Это классический Switch Code Smell, вот пример с картинкой: https://elearning.industriallogic.com/gh/submit?Action=PageAction&album=recognizingSmells&path=recognizingSmells/moreCommonCodeSmells/switchStatementExample&devLanguage=Java

Автор: amarenkov 26.6.2009, 06:35
Цитата(PashaPash @  25.6.2009,  15:08 Найти цитируемый пост)
... а вынести типозависымый код в виртуальные функции. 

Не получится smile. 

Задача (если сильно упростить) сводится к работе с графическими объектами. Есть базовый Figure, и есть наследники: Point, Line, Polygon и т.п.

И есть функция отрисовки. Вне этих классов. Вносить эту функцию в них я категорически не хочу, т.к. это было бы некорректно с точки зрения модели smile.

Вот, собственно, и все. В функцию отрисовки передается Figure. Функция должна узнать, что это за фигура такая и отрисовать ее.

Автор: amarenkov 26.6.2009, 06:54
В принципе, вопрос снимается.

Сделал простой тест, и на 1 000 000 объектов проверка через перечислимый тип дает 156 250 тиков, а через is - 312 500. 

Жаль smile. Хотелось сделать красивее, через is, но быстрее через перечислимый тип.

Автор: KelTron 26.6.2009, 07:18
Хоть это и банально, но
"Преждевременная оптимизация - корень всех зол"

Вот если после написания прога будет тормозить, и профайлер покажет, что данная проверка это слабое место по производительности, тогда и оптимизируй. Хотя многие опытные люди говорят, что обычно слабое место оказывается совсем не там где предполагали разработчики, а от оптимизации второстепенных(в плане производительности) кусков кода толку будет мало и читабельность программы ухудшится.


Автор: Partizan 26.6.2009, 10:25
Цитата(amarenkov @ 26.6.2009,  06:35)
Цитата(PashaPash @  25.6.2009,  15:08 Найти цитируемый пост)
... а вынести типозависымый код в виртуальные функции. 

Не получится smile. 

Задача (если сильно упростить) сводится к работе с графическими объектами. Есть базовый Figure, и есть наследники: Point, Line, Polygon и т.п.

И есть функция отрисовки. Вне этих классов. Вносить эту функцию в них я категорически не хочу, т.к. это было бы некорректно с точки зрения модели smile.

Вот, собственно, и все. В функцию отрисовки передается Figure. Функция должна узнать, что это за фигура такая и отрисовать ее.

amarenkov,

Что мешает в каждый из классов добавить виртуальный метод Render, когда каждый элемент сам знает как себя нарисовать?

Автор: PashaPash 26.6.2009, 10:25
Цитата(amarenkov @  26.6.2009,  06:35 Найти цитируемый пост)

И есть функция отрисовки. Вне этих классов. Вносить эту функцию в них я категорически не хочу, т.к. это было бы некорректно с точки зрения модели

Это вообще-то корректно с точки зрения модели, более того - пример с фигурами и функцией отрисовки есть практически в любой книжке по ООП, в главе про полиморфизм. Настолько корректно, что пример даже есть в MSDN, в топике http://msdn.microsoft.com/ru-ru/library/ms173152.aspx. Figure по ненашему Shape, кстати.
Цитата(amarenkov @  26.6.2009,  06:54 Найти цитируемый пост)

Сделал простой тест, и на 1 000 000 объектов проверка через перечислимый тип дает 156 250 тиков, а через is - 312 500. 
Жаль smile. Хотелось сделать красивее, через is, но быстрее через перечислимый тип. 

А если включить саму отрисовку, то результат будет 300 и 301. 1 тик стоит жертвы. 

Автор: mihryak 26.6.2009, 11:25
не хочешь в классе делать (например, если класс этот представляет из себя нечто вроде DTO) - вынеси в стратегию
только тогда придётся параллельно вести две иерархии, что само по себе не очень удобно, но порой оправдано
Код

    abstract class Figure
    {
        private readonly IRenderStrategy strategy;

        protected Figure(IRenderStrategy strategy)
        {
            this.strategy = strategy;
        }

        public void Render()
        {
            strategy.Render(this);
        }
    }

    interface IRenderStrategy
    {
        void Render(Figure figure);
    }

    class Square : Figure
    {
        public Square() : base(new SquareRenderStrategy())
        {
        }
    }

    class SquareRenderStrategy : IRenderStrategy
    {
        public void Render(Figure figure)
        {
            // render actions
        }
    }

Автор: Partizan 26.6.2009, 12:31
mihryak, сорри...не очень ясно с какой целью Figure ака Shape в метод Render передавать надобно?


а то получается какая-то циклическая зависимость... Figure содержит IRenderStrategy...а потом в Render этого интерфейса тоже надо передать Figure... просто сугубо интересно - зачем?

Автор: mihryak 26.6.2009, 12:46
хм, это вполне обычный ход

конкретная фигура имеет собственную стратегию отрисовки, а стратегия общая для всех фигур определённого класса
это может позволить, например, держать один инстанс стратегии на все её фигуры, позволяет сделать её stateless

Автор: Partizan 26.6.2009, 13:07
mihryak, ok, идея ясна  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)