Я просто пересматриваю главу 4 С# в Depth, которая имеет дело с типами NULL, и я добавляю раздел об использовании оператора "as", который позволяет вам написать:
object o = ...;
int? x = o as int?;
if (x.HasValue)
{
    ... // Use x.Value in here
}
Я думал, что это было очень аккуратно, и что это может повысить производительность над эквивалентом С# 1, используя "is", за которым следует бросок. В конце концов, нам нужно только один раз запросить проверку динамического типа, а затем простая проверка значения.
Это, похоже, не так. Я включил тестовое приложение ниже, которое в основном суммирует все целые числа в массиве объектов, но массив содержит множество нулевых ссылок и ссылок на строки, а также целые числа в штучной упаковке. Эталонный показатель измеряет код, который вы должны использовать в С# 1, код с использованием оператора "as" и просто для решения LINQ. К моему удивлению, код С# 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);
    }
}


