Почему реализация SortedList использует ThrowHelper вместо того, чтобы бросить непосредственно?

Я столкнулся с той же проблемой «Код ошибки: 0xC0048021» и решил ее.

Я установил эту версию SSDT здесь https://msdn.microsoft.com/en-us/mt429383

Затем в решении SSDT explorer щелкните правой кнопкой мыши Project, перейдите в Свойства -> Свойства конфигурации -> TargetServerVersion = SQL SERVER 2014

Затем в проводнике SSDT щелкните правой кнопкой мыши Project, перейдите в Properties -> Configuration Свойства -> Отладка -> Run64BitRuntime = False

Ссылка на эту ссылку http://blogs.msdn.com/b/ssis/archive/2016/03/03/what-s -new-for-ssis-2016-rc0.aspx

13
задан Roman Starkov 18 February 2009 в 19:28
поделиться

3 ответа

Согласно исходному коду ThrowHelper.cs основная цель - уменьшить размер кода JITted. Ниже приведена прямая копия вставки по ссылке:

// This file defines an internal class used to throw exceptions in BCL code.
// The main purpose is to reduce code size. 
// 
// The old way to throw an exception generates quite a lot IL code and assembly code.
// Following is an example:
//     C# source
//          throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
//     IL code:
//          IL_0003:  ldstr      "key"
//          IL_0008:  ldstr      "ArgumentNull_Key"
//          IL_000d:  call       string System.Environment::GetResourceString(string)
//          IL_0012:  newobj     instance void System.ArgumentNullException::.ctor(string,string)
//          IL_0017:  throw
//    which is 21bytes in IL.
// 
// So we want to get rid of the ldstr and call to Environment.GetResource in IL.
// In order to do that, I created two enums: ExceptionResource, ExceptionArgument to represent the
// argument name and resource name in a small integer. The source code will be changed to 
//    ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key, ExceptionResource.ArgumentNull_Key);
//
// The IL code will be 7 bytes.
//    IL_0008:  ldc.i4.4
//    IL_0009:  ldc.i4.4
//    IL_000a:  call       void System.ThrowHelper::ThrowArgumentNullException(valuetype System.ExceptionArgument)
//    IL_000f:  ldarg.0
//
// This will also reduce the Jitted code size a lot. 
21
ответ дан 1 December 2019 в 21:38
поделиться

Посмотрите на то, что делает ThrowHelper. Это получает ресурсы и материал для сообщений об ошибках. В этом конкретном экземпляре нет никакого текста ошибки, таким образом, кажется, что это бесполезно, но их шаблон, вероятно, требует его, таким образом, разработчик, который записал это, следовал за шаблоном как, он или она должен.

4
ответ дан 1 December 2019 в 21:38
поделиться

Другим интересным аспектом является производительность. Интересно достаточно метод, который содержит throw оператор, может быть медленнее, даже если исключение не выдается просто, потому что JIT предпочитает не встраивать такие методы (возможно, к лучшему удобочитаемость стека вызовов). Рассмотрите следующий пример:

private class TestClass
{
    internal int RegularThrow(int value)
    {
        if (value < 0)
            throw new ArgumentOutOfRangeException(nameof(value));
        return value + 1;
    }

    internal int ThrowByHelper(int value)
    {
        if (value < 0)
            Throw.ArgumentOutOfRangeException(Argument.value); // Argument is an enum
        return value + 1;
    }
}

Результаты проверки производительности на моем компьютере:

(См., что источник связывается наряду с некоторыми комментариями ниже)

1. ThrowByHelper: average time: 5,24 ms
  #1           5,26 ms
  #2           5,16 ms   <---- Best
  #3           5,31 ms   <---- Worst
  Worst-Best difference: 0,16 ms (3,02%)
2. RegularThrow: average time: 23,51 ms (+18,27 ms / 448,40%)
  #1          23,46 ms
  #2          23,42 ms   <---- Best
  #3          23,65 ms   <---- Worst
  Worst-Best difference: 0,22 ms (0,95%)

Значение, метод с явным throw оператор был в 4.5 раза медленнее! Но...

Интересные Наблюдения:

  • Запуск с.NET 4.0 можно подать заявку эти [MethodImpl(MethodImplOptions.AggressiveInlining)] атрибут, хотя это ничего не гарантирует. Например, во встраивании Скрипки.NET, кажется, обычно отключается, следовательно оба пути имеют эффективно ту же производительность. Посмотрите исходный код и совершенно другие результаты здесь .
  • В.NET Core 3 (x64 сборка конечных версий в Windows 10) кажется что только типы исключительной ситуации, полученные от ArgumentException предотвращенное встраивание (не используя атрибутов). По крайней мере, бросок NotSupportedException или InvalidOperationException непосредственно не влиял на производительность негативно.
  • Для более сложных методов помощник броска не имеет никакого смысла так или иначе. Но это может быть полезно в коротких критических по отношению к производительности участниках.

Избыточная/недостижимая проблема кода и анализаторы кода:

избыточное return оператора можно избежать путем определения некоторых универсальных перегрузок в ThrowHelper:

// for regular usage:
internal static void ArgumentException(Argument arg, string message) => throw new...

// for expression usage:
internal static T ArgumentException<T>(Argument arg, string message) => throw new...

последний может использоваться в return оператор, может сэкономить break в [1 115] блоки и запускающийся с C# 7.0, он может использоваться тот же путь в качестве выражений отсеивания:

return value >= 0 ? value + 1 : Throw.ArgumentOutOfRangeException<int>(Argument.value);

Другая проблема - то, что ReSharper и FxCop не распознают участников помощника броска и могут начать испускать ложные положительные предупреждения. Для ReSharper мы можем использовать эти ContractAnnotation атрибут:

// prevents PossibleNullReferenceException, AssignNullToNotNullAttribute and similar false alarms
[ContractAnnotation("=> halt")]
internal static void ArgumentException(Argument arg, string message) => throw new...

К сожалению для FxCop я не нашел аналогичное решение (и эти [DoesNotReturn], атрибут, по-видимому, не работает), таким образом, необходимо использовать #pragma warning disable или эти SuppressMessage атрибут для подавления CA1031, CA1062 и их друзей.

0
ответ дан 1 December 2019 в 21:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: