Я просто пересматриваю главу 4 из C# в Depth, которая имеет дело с типами NULL, и я добавляю раздел об использовании оператора «as», который позволяет вам писать:Удивительный сюрприз с типами «как» и «с нулевым числом»
object o = ...;
int? x = o as int?;
if (x.HasValue)
{
... // Use x.Value in here
}
Я думал, что это было очень аккуратно, и что это может улучшить производительность по сравнению с C# 1 эквивалент, используя «в», а затем броском - в конце концов, таким образом, нам нужно только попросить для проверки один раз динамический тип , а затем простая проверка значения.
Это, похоже, не так. Я включил тестовое приложение ниже, которое в основном суммирует все целые числа в массиве объектов, но массив содержит множество нулевых ссылок и ссылок на строки, а также целые числа в штучной упаковке. Эталонный показатель измеряет код, который вы должны использовать в C# 1, код с использованием оператора «as» и просто для решения LINQ. К моему удивлению, код C# 1 в этом случае в 20 раз быстрее - и даже код LINQ (который я ожидал бы медленнее, учитывая задействованные итераторы) превосходит код «как».
Является ли реализация .NET для isinst
для типов с нулевым значением только очень медленным? Является ли это дополнительным unbox.any
, что вызывает проблему? Есть ли еще одно объяснение этому? В настоящее время он чувствует, как я буду иметь, чтобы включить предупреждение против использования этого в производительности сложных ситуациях ...
Результаты:
В ролях: 10000000: 121
Как: 10000000: 2211
LINQ: 10000000: 2143
Код:
using System;
using System.Diagnostics;
using System.Linq;
class Test
{
const int Size = 30000000;
static void Main()
{
object[] values = new object[Size];
for (int i = 0; i < Size - 2; i += 3)
{
values[i] = null;
values[i+1] = "";
values[i+2] = 1;
}
FindSumWithCast(values);
FindSumWithAs(values);
FindSumWithLinq(values);
}
static void FindSumWithCast(object[] values)
{
Stopwatch sw = Stopwatch.StartNew();
int sum = 0;
foreach (object o in values)
{
if (o is int)
{
int x = (int) o;
sum += x;
}
}
sw.Stop();
Console.WriteLine("Cast: {0} : {1}", sum,
(long) sw.ElapsedMilliseconds);
}
static void FindSumWithAs(object[] values)
{
Stopwatch sw = Stopwatch.StartNew();
int sum = 0;
foreach (object o in values)
{
int? x = o as int?;
if (x.HasValue)
{
sum += x.Value;
}
}
sw.Stop();
Console.WriteLine("As: {0} : {1}", sum,
(long) sw.ElapsedMilliseconds);
}
static void FindSumWithLinq(object[] values)
{
Stopwatch sw = Stopwatch.StartNew();
int sum = values.OfType<int>().Sum();
sw.Stop();
Console.WriteLine("LINQ: {0} : {1}", sum,
(long) sw.ElapsedMilliseconds);
}
}
Почему бы не посмотреть на jitted-код? Даже отладчик VS может показать это. –
Мне просто интересно, вы тоже проверили CLR 4.0? –
@ Антон: Хорошая точка. Сделаю в какой-то момент (хотя в настоящий момент это не в VS :) @divo: Да, и все хуже. Но тогда это в бета-версии, поэтому там может быть много отладочного кода. –