The Labs \ Source Viewer \ SSCLI \ System \ ThrowHelper

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace System
  16. {
  17.     // This file defines an internal class used to throw exceptions in BCL code.
  18.     // The main purpose is to reduce code size.
  19.     //
  20.     // The old way to throw an exception generates quite a lot IL code and assembly code.
  21.     // Following is an example:
  22.     // C# source
  23.     // throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
  24.     // IL code:
  25.     // IL_0003: ldstr "key"
  26.     // IL_0008: ldstr "ArgumentNull_Key"
  27.     // IL_000d: call string System.Environment::GetResourceString(string)
  28.     // IL_0012: newobj instance void System.ArgumentNullException::.ctor(string,string)
  29.     // IL_0017: throw
  30.     // which is 21bytes in IL.
  31.     //
  32.     // So we want to get rid of the ldstr and call to Environment.GetResource in IL.
  33.     // In order to do that, I created two enums: ExceptionResource, ExceptionArgument to represent the
  34.     // argument name and resource name in a small integer. The source code will be changed to
  35.     // ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key, ExceptionResource.ArgumentNull_Key);
  36.     //
  37.     // The IL code will be 7 bytes.
  38.     // IL_0008: ldc.i4.4
  39.     // IL_0009: ldc.i4.4
  40.     // IL_000a: call void System.ThrowHelper::ThrowArgumentNullException(valuetype System.ExceptionArgument)
  41.     // IL_000f: ldarg.0
  42.     //
  43.     // This will also reduce the Jitted code size a lot.
  44.     //
  45.     // It is very important we do this for generic classes because we can easily generate the same code
  46.     // multiple times for different instantiation.
  47.     //
  48.     //
  49.    
  50.     using System.Runtime.CompilerServices;
  51.     using System.Runtime.Serialization;
  52.     static internal class ThrowHelper
  53.     {
  54.         [MethodImplAttribute(MethodImplOptions.NoInlining)]
  55.         static internal void ThrowArgumentOutOfRangeException()
  56.         {
  57.             ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
  58.         }
  59.        
  60.         static internal void ThrowWrongKeyTypeArgumentException(object key, Type targetType)
  61.         {
  62.             throw new ArgumentException(Environment.GetResourceString("Arg_WrongType", key, targetType), "key");
  63.         }
  64.        
  65.         static internal void ThrowWrongValueTypeArgumentException(object value, Type targetType)
  66.         {
  67.             throw new ArgumentException(Environment.GetResourceString("Arg_WrongType", value, targetType), "value");
  68.         }
  69.        
  70.         static internal void ThrowKeyNotFoundException()
  71.         {
  72.             throw new System.Collections.Generic.KeyNotFoundException();
  73.         }
  74.        
  75.         static internal void ThrowArgumentException(ExceptionResource resource)
  76.         {
  77.             throw new ArgumentException(Environment.GetResourceString(GetResourceName(resource)));
  78.         }
  79.        
  80.         static internal void ThrowArgumentException(ExceptionResource resource, ExceptionArgument argument)
  81.         {
  82.             throw new ArgumentException(Environment.GetResourceString(GetResourceName(resource)), GetArgumentName(argument));
  83.         }
  84.        
  85.         static internal void ThrowArgumentNullException(ExceptionArgument argument)
  86.         {
  87.             throw new ArgumentNullException(GetArgumentName(argument));
  88.         }
  89.        
  90.         static internal void ThrowArgumentOutOfRangeException(ExceptionArgument argument)
  91.         {
  92.             throw new ArgumentOutOfRangeException(GetArgumentName(argument));
  93.         }
  94.        
  95.         static internal void ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
  96.         {
  97.             throw new ArgumentOutOfRangeException(GetArgumentName(argument), Environment.GetResourceString(GetResourceName(resource)));
  98.         }
  99.        
  100.         static internal void ThrowInvalidOperationException(ExceptionResource resource)
  101.         {
  102.             throw new InvalidOperationException(Environment.GetResourceString(GetResourceName(resource)));
  103.         }
  104.        
  105.         static internal void ThrowSerializationException(ExceptionResource resource)
  106.         {
  107.             throw new SerializationException(Environment.GetResourceString(GetResourceName(resource)));
  108.         }
  109.        
  110.         static internal void ThrowSecurityException(ExceptionResource resource)
  111.         {
  112.             throw new System.Security.SecurityException(Environment.GetResourceString(GetResourceName(resource)));
  113.         }
  114.        
  115.         static internal void ThrowNotSupportedException(ExceptionResource resource)
  116.         {
  117.             throw new NotSupportedException(Environment.GetResourceString(GetResourceName(resource)));
  118.         }
  119.        
  120.         static internal void ThrowUnauthorizedAccessException(ExceptionResource resource)
  121.         {
  122.             throw new UnauthorizedAccessException(Environment.GetResourceString(GetResourceName(resource)));
  123.         }
  124.        
  125.         static internal void ThrowObjectDisposedException(string objectName, ExceptionResource resource)
  126.         {
  127.             throw new ObjectDisposedException(objectName, Environment.GetResourceString(GetResourceName(resource)));
  128.         }
  129.        
  130.         //
  131.         // This function will convert an ExceptionArgument enum value to the argument name string.
  132.         //
  133.         static internal string GetArgumentName(ExceptionArgument argument)
  134.         {
  135.             string argumentName = null;
  136.            
  137.             switch (argument) {
  138.                 case ExceptionArgument.array:
  139.                     argumentName = "array";
  140.                     break;
  141.                 case ExceptionArgument.arrayIndex:
  142.                    
  143.                     argumentName = "arrayIndex";
  144.                     break;
  145.                 case ExceptionArgument.capacity:
  146.                    
  147.                     argumentName = "capacity";
  148.                     break;
  149.                 case ExceptionArgument.collection:
  150.                    
  151.                     argumentName = "collection";
  152.                     break;
  153.                 case ExceptionArgument.list:
  154.                    
  155.                     argumentName = "list";
  156.                     break;
  157.                 case ExceptionArgument.converter:
  158.                    
  159.                     argumentName = "converter";
  160.                     break;
  161.                 case ExceptionArgument.count:
  162.                    
  163.                     argumentName = "count";
  164.                     break;
  165.                 case ExceptionArgument.dictionary:
  166.                    
  167.                     argumentName = "dictionary";
  168.                     break;
  169.                 case ExceptionArgument.dictionaryCreationThreshold:
  170.                    
  171.                     argumentName = "dictionaryCreationThreshold";
  172.                     break;
  173.                 case ExceptionArgument.index:
  174.                    
  175.                     argumentName = "index";
  176.                     break;
  177.                 case ExceptionArgument.info:
  178.                    
  179.                     argumentName = "info";
  180.                     break;
  181.                 case ExceptionArgument.key:
  182.                    
  183.                     argumentName = "key";
  184.                     break;
  185.                 case ExceptionArgument.match:
  186.                    
  187.                     argumentName = "match";
  188.                     break;
  189.                 case ExceptionArgument.obj:
  190.                    
  191.                     argumentName = "obj";
  192.                     break;
  193.                 case ExceptionArgument.queue:
  194.                    
  195.                     argumentName = "queue";
  196.                     break;
  197.                 case ExceptionArgument.stack:
  198.                    
  199.                     argumentName = "stack";
  200.                     break;
  201.                 case ExceptionArgument.startIndex:
  202.                    
  203.                     argumentName = "startIndex";
  204.                     break;
  205.                 case ExceptionArgument.value:
  206.                    
  207.                     argumentName = "value";
  208.                     break;
  209.                 case ExceptionArgument.name:
  210.                    
  211.                     argumentName = "name";
  212.                     break;
  213.                 case ExceptionArgument.mode:
  214.                    
  215.                     argumentName = "mode";
  216.                     break;
  217.                 default:
  218.                    
  219.                     BCLDebug.Assert(false, "The enum value is not defined, please checked ExceptionArgumentName Enum.");
  220.                     return string.Empty;
  221.             }
  222.            
  223.             return argumentName;
  224.         }
  225.        
  226.         //
  227.         // This function will convert an ExceptionResource enum value to the resource string.
  228.         //
  229.         static internal string GetResourceName(ExceptionResource resource)
  230.         {
  231.             string resourceName = null;
  232.            
  233.             switch (resource) {
  234.                 case ExceptionResource.Argument_ImplementIComparable:
  235.                     resourceName = "Argument_ImplementIComparable";
  236.                     break;
  237.                 case ExceptionResource.Argument_AddingDuplicate:
  238.                    
  239.                     resourceName = "Argument_AddingDuplicate";
  240.                     break;
  241.                 case ExceptionResource.ArgumentOutOfRange_BiggerThanCollection:
  242.                    
  243.                     resourceName = "ArgumentOutOfRange_BiggerThanCollection";
  244.                     break;
  245.                 case ExceptionResource.ArgumentOutOfRange_Count:
  246.                    
  247.                     resourceName = "ArgumentOutOfRange_Count";
  248.                     break;
  249.                 case ExceptionResource.ArgumentOutOfRange_Index:
  250.                    
  251.                     resourceName = "ArgumentOutOfRange_Index";
  252.                     break;
  253.                 case ExceptionResource.ArgumentOutOfRange_InvalidThreshold:
  254.                    
  255.                     resourceName = "ArgumentOutOfRange_InvalidThreshold";
  256.                     break;
  257.                 case ExceptionResource.ArgumentOutOfRange_ListInsert:
  258.                    
  259.                     resourceName = "ArgumentOutOfRange_ListInsert";
  260.                     break;
  261.                 case ExceptionResource.ArgumentOutOfRange_NeedNonNegNum:
  262.                    
  263.                     resourceName = "ArgumentOutOfRange_NeedNonNegNum";
  264.                     break;
  265.                 case ExceptionResource.ArgumentOutOfRange_SmallCapacity:
  266.                    
  267.                     resourceName = "ArgumentOutOfRange_SmallCapacity";
  268.                     break;
  269.                 case ExceptionResource.Arg_ArrayPlusOffTooSmall:
  270.                    
  271.                     resourceName = "Arg_ArrayPlusOffTooSmall";
  272.                     break;
  273.                 case ExceptionResource.Arg_RankMultiDimNotSupported:
  274.                    
  275.                     resourceName = "Arg_RankMultiDimNotSupported";
  276.                     break;
  277.                 case ExceptionResource.Arg_NonZeroLowerBound:
  278.                    
  279.                     resourceName = "Arg_NonZeroLowerBound";
  280.                     break;
  281.                 case ExceptionResource.Argument_InvalidArrayType:
  282.                    
  283.                     resourceName = "Argument_InvalidArrayType";
  284.                     break;
  285.                 case ExceptionResource.Argument_InvalidOffLen:
  286.                    
  287.                     resourceName = "Argument_InvalidOffLen";
  288.                     break;
  289.                 case ExceptionResource.Argument_ItemNotExist:
  290.                    
  291.                     resourceName = "Argument_ItemNotExist";
  292.                     break;
  293.                 case ExceptionResource.InvalidOperation_CannotRemoveFromStackOrQueue:
  294.                    
  295.                     resourceName = "InvalidOperation_CannotRemoveFromStackOrQueue";
  296.                     break;
  297.                 case ExceptionResource.InvalidOperation_EmptyQueue:
  298.                    
  299.                     resourceName = "InvalidOperation_EmptyQueue";
  300.                     break;
  301.                 case ExceptionResource.InvalidOperation_EnumOpCantHappen:
  302.                    
  303.                     resourceName = "InvalidOperation_EnumOpCantHappen";
  304.                     break;
  305.                 case ExceptionResource.InvalidOperation_EnumFailedVersion:
  306.                    
  307.                     resourceName = "InvalidOperation_EnumFailedVersion";
  308.                     break;
  309.                 case ExceptionResource.InvalidOperation_EmptyStack:
  310.                    
  311.                     resourceName = "InvalidOperation_EmptyStack";
  312.                     break;
  313.                 case ExceptionResource.InvalidOperation_EnumNotStarted:
  314.                    
  315.                     resourceName = "InvalidOperation_EnumNotStarted";
  316.                     break;
  317.                 case ExceptionResource.InvalidOperation_EnumEnded:
  318.                    
  319.                     resourceName = "InvalidOperation_EnumEnded";
  320.                     break;
  321.                 case ExceptionResource.NotSupported_KeyCollectionSet:
  322.                    
  323.                     resourceName = "NotSupported_KeyCollectionSet";
  324.                     break;
  325.                 case ExceptionResource.NotSupported_ReadOnlyCollection:
  326.                    
  327.                     resourceName = "NotSupported_ReadOnlyCollection";
  328.                     break;
  329.                 case ExceptionResource.NotSupported_ValueCollectionSet:
  330.                    
  331.                     resourceName = "NotSupported_ValueCollectionSet";
  332.                     break;
  333.                 case ExceptionResource.NotSupported_SortedListNestedWrite:
  334.                    
  335.                    
  336.                     resourceName = "NotSupported_SortedListNestedWrite";
  337.                     break;
  338.                 case ExceptionResource.Serialization_InvalidOnDeser:
  339.                    
  340.                    
  341.                     resourceName = "Serialization_InvalidOnDeser";
  342.                     break;
  343.                 case ExceptionResource.Serialization_MissingKeyValuePairs:
  344.                    
  345.                     resourceName = "Serialization_MissingKeyValuePairs";
  346.                     break;
  347.                 case ExceptionResource.Serialization_NullKey:
  348.                    
  349.                     resourceName = "Serialization_NullKey";
  350.                     break;
  351.                 case ExceptionResource.Argument_InvalidType:
  352.                    
  353.                     resourceName = "Argument_InvalidType";
  354.                     break;
  355.                 case ExceptionResource.Argument_InvalidArgumentForComparison:
  356.                    
  357.                     resourceName = "Argument_InvalidArgumentForComparison";
  358.                     break;
  359.                 case ExceptionResource.InvalidOperation_NoValue:
  360.                    
  361.                     resourceName = "InvalidOperation_NoValue";
  362.                     break;
  363.                 case ExceptionResource.InvalidOperation_RegRemoveSubKey:
  364.                    
  365.                     resourceName = "InvalidOperation_RegRemoveSubKey";
  366.                     break;
  367.                 case ExceptionResource.Arg_RegSubKeyAbsent:
  368.                    
  369.                     resourceName = "Arg_RegSubKeyAbsent";
  370.                     break;
  371.                 case ExceptionResource.Arg_RegSubKeyValueAbsent:
  372.                    
  373.                     resourceName = "Arg_RegSubKeyValueAbsent";
  374.                     break;
  375.                 case ExceptionResource.Arg_RegKeyDelHive:
  376.                    
  377.                     resourceName = "Arg_RegKeyDelHive";
  378.                     break;
  379.                 case ExceptionResource.Security_RegistryPermission:
  380.                    
  381.                     resourceName = "Security_RegistryPermission";
  382.                     break;
  383.                 case ExceptionResource.Arg_RegSetStrArrNull:
  384.                    
  385.                     resourceName = "Arg_RegSetStrArrNull";
  386.                     break;
  387.                 case ExceptionResource.Arg_RegSetMismatchedKind:
  388.                    
  389.                     resourceName = "Arg_RegSetMismatchedKind";
  390.                     break;
  391.                 case ExceptionResource.UnauthorizedAccess_RegistryNoWrite:
  392.                    
  393.                     resourceName = "UnauthorizedAccess_RegistryNoWrite";
  394.                     break;
  395.                 case ExceptionResource.ObjectDisposed_RegKeyClosed:
  396.                    
  397.                     resourceName = "ObjectDisposed_RegKeyClosed";
  398.                     break;
  399.                 case ExceptionResource.Arg_RegKeyStrLenBug:
  400.                    
  401.                     resourceName = "Arg_RegKeyStrLenBug";
  402.                     break;
  403.                 case ExceptionResource.Argument_InvalidRegistryKeyPermissionCheck:
  404.                    
  405.                     resourceName = "Argument_InvalidRegistryKeyPermissionCheck";
  406.                     break;
  407.                 case ExceptionResource.NotSupported_InComparableType:
  408.                    
  409.                     resourceName = "NotSupported_InComparableType";
  410.                     break;
  411.                 default:
  412.                    
  413.                     BCLDebug.Assert(false, "The enum value is not defined, please checked ExceptionArgumentName Enum.");
  414.                     return string.Empty;
  415.             }
  416.            
  417.             return resourceName;
  418.         }
  419.        
  420.     }
  421.    
  422.     //
  423.     // The convention for this enum is using the argument name as the enum name
  424.     //
  425.     internal enum ExceptionArgument
  426.     {
  427.         obj,
  428.         dictionary,
  429.         dictionaryCreationThreshold,
  430.         array,
  431.         info,
  432.         key,
  433.         collection,
  434.         list,
  435.         match,
  436.         converter,
  437.         queue,
  438.         stack,
  439.         capacity,
  440.         index,
  441.         startIndex,
  442.         value,
  443.         count,
  444.         arrayIndex,
  445.         name,
  446.         mode
  447.     }
  448.    
  449.     //
  450.     // The convention for this enum is using the resource name as the enum name
  451.     //
  452.     internal enum ExceptionResource
  453.     {
  454.         Argument_ImplementIComparable,
  455.         Argument_InvalidType,
  456.         Argument_InvalidArgumentForComparison,
  457.         Argument_InvalidRegistryKeyPermissionCheck,
  458.         ArgumentOutOfRange_NeedNonNegNum,
  459.        
  460.         Arg_ArrayPlusOffTooSmall,
  461.         Arg_NonZeroLowerBound,
  462.         Arg_RankMultiDimNotSupported,
  463.         Arg_RegKeyDelHive,
  464.         Arg_RegKeyStrLenBug,
  465.         Arg_RegSetStrArrNull,
  466.         Arg_RegSetMismatchedKind,
  467.         Arg_RegSubKeyAbsent,
  468.         Arg_RegSubKeyValueAbsent,
  469.        
  470.         Argument_AddingDuplicate,
  471.         Serialization_InvalidOnDeser,
  472.         Serialization_MissingKeyValuePairs,
  473.         Serialization_NullKey,
  474.         Argument_InvalidArrayType,
  475.         NotSupported_KeyCollectionSet,
  476.         NotSupported_ValueCollectionSet,
  477.         ArgumentOutOfRange_SmallCapacity,
  478.         ArgumentOutOfRange_Index,
  479.         Argument_InvalidOffLen,
  480.         Argument_ItemNotExist,
  481.         ArgumentOutOfRange_Count,
  482.         ArgumentOutOfRange_InvalidThreshold,
  483.         ArgumentOutOfRange_ListInsert,
  484.         NotSupported_ReadOnlyCollection,
  485.         InvalidOperation_CannotRemoveFromStackOrQueue,
  486.         InvalidOperation_EmptyQueue,
  487.         InvalidOperation_EnumOpCantHappen,
  488.         InvalidOperation_EnumFailedVersion,
  489.         InvalidOperation_EmptyStack,
  490.         ArgumentOutOfRange_BiggerThanCollection,
  491.         InvalidOperation_EnumNotStarted,
  492.         InvalidOperation_EnumEnded,
  493.         NotSupported_SortedListNestedWrite,
  494.         InvalidOperation_NoValue,
  495.         InvalidOperation_RegRemoveSubKey,
  496.         Security_RegistryPermission,
  497.         UnauthorizedAccess_RegistryNoWrite,
  498.         ObjectDisposed_RegKeyClosed,
  499.         NotSupported_InComparableType
  500.     }
  501. }

Developer Fusion