diff options
Diffstat (limited to 'src/mscorlib/src/System/ThrowHelper.cs')
-rw-r--r-- | src/mscorlib/src/System/ThrowHelper.cs | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/ThrowHelper.cs b/src/mscorlib/src/System/ThrowHelper.cs new file mode 100644 index 0000000000..3105d56f7c --- /dev/null +++ b/src/mscorlib/src/System/ThrowHelper.cs @@ -0,0 +1,347 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +namespace System { + // 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. + // + // It is very important we do this for generic classes because we can easily generate the same code + // multiple times for different instantiation. + // + + using Collections.Generic; + using System.Runtime.CompilerServices; + using System.Runtime.Serialization; + using System.Diagnostics.Contracts; + + [Pure] + internal static class ThrowHelper { + internal static void ThrowArgumentOutOfRange_IndexException() { + throw new ArgumentOutOfRangeException(GetArgumentName(ExceptionArgument.index), + Environment.GetResourceString(GetResourceName(ExceptionResource.ArgumentOutOfRange_Index))); + } + + internal static void ThrowIndexArgumentOutOfRange_NeedNonNegNumException() { + throw new ArgumentOutOfRangeException( + GetArgumentName(ExceptionArgument.index), + Environment.GetResourceString(GetResourceName(ExceptionResource.ArgumentOutOfRange_NeedNonNegNum))); + } + + internal static void ThrowWrongKeyTypeArgumentException(object key, Type targetType) { + throw new ArgumentException(Environment.GetResourceString("Arg_WrongType", key, targetType), "key"); + } + + internal static void ThrowWrongValueTypeArgumentException(object value, Type targetType) { + throw new ArgumentException(Environment.GetResourceString("Arg_WrongType", value, targetType), "value"); + } + +#if FEATURE_CORECLR + internal static void ThrowAddingDuplicateWithKeyArgumentException(object key) { + throw new ArgumentException(Environment.GetResourceString("Argument_AddingDuplicateWithKey", key)); + } +#endif + + internal static void ThrowKeyNotFoundException() { + throw new System.Collections.Generic.KeyNotFoundException(); + } + + internal static void ThrowArgumentException(ExceptionResource resource) { + throw new ArgumentException(Environment.GetResourceString(GetResourceName(resource))); + } + + internal static void ThrowArgumentException(ExceptionResource resource, ExceptionArgument argument) { + throw new ArgumentException(Environment.GetResourceString(GetResourceName(resource)), GetArgumentName(argument)); + } + + internal static void ThrowArgumentNullException(ExceptionArgument argument) { + throw new ArgumentNullException(GetArgumentName(argument)); + } + + internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument) { + throw new ArgumentOutOfRangeException(GetArgumentName(argument)); + } + + internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource) { + throw new ArgumentOutOfRangeException(GetArgumentName(argument), + Environment.GetResourceString(GetResourceName(resource))); + } + + internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, int paramNumber, ExceptionResource resource) { + throw new ArgumentOutOfRangeException(GetArgumentName(argument) + "[" + paramNumber.ToString() + "]", + Environment.GetResourceString(GetResourceName(resource))); + } + + internal static void ThrowInvalidOperationException(ExceptionResource resource) { + throw new InvalidOperationException(Environment.GetResourceString(GetResourceName(resource))); + } + + internal static void ThrowInvalidOperationException(ExceptionResource resource, Exception e) { + throw new InvalidOperationException(Environment.GetResourceString(GetResourceName(resource)), e); + } + + internal static void ThrowSerializationException(ExceptionResource resource) { + throw new SerializationException(Environment.GetResourceString(GetResourceName(resource))); + } + + internal static void ThrowSecurityException(ExceptionResource resource) { + throw new System.Security.SecurityException(Environment.GetResourceString(GetResourceName(resource))); + } + + internal static void ThrowRankException(ExceptionResource resource) { + throw new RankException(Environment.GetResourceString(GetResourceName(resource))); + } + + internal static void ThrowNotSupportedException(ExceptionResource resource) { + throw new NotSupportedException(Environment.GetResourceString(GetResourceName(resource))); + } + + internal static void ThrowUnauthorizedAccessException(ExceptionResource resource) { + throw new UnauthorizedAccessException(Environment.GetResourceString(GetResourceName(resource))); + } + + internal static void ThrowObjectDisposedException(string objectName, ExceptionResource resource) { + throw new ObjectDisposedException(objectName, Environment.GetResourceString(GetResourceName(resource))); + } + + internal static void ThrowObjectDisposedException(ExceptionResource resource) + { + throw new ObjectDisposedException(null, Environment.GetResourceString(GetResourceName(resource))); + } + + internal static void ThrowNotSupportedException() + { + throw new NotSupportedException(); + } + + internal static void ThrowAggregateException(List<Exception> exceptions) + { + throw new AggregateException(exceptions); + } + + // Allow nulls for reference types and Nullable<U>, but not for value types. + // Aggressively inline so the jit evaluates the if in place and either drops the call altogether + // Or just leaves null test and call to the Non-returning ThrowHelper.ThrowArgumentNullException + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void IfNullAndNullsAreIllegalThenThrow<T>(object value, ExceptionArgument argName) { + // Note that default(T) is not equal to null for value types except when T is Nullable<U>. + if (!(default(T) == null) && value == null) + ThrowHelper.ThrowArgumentNullException(argName); + } + + // + // This function will convert an ExceptionArgument enum value to the argument name string. + // + internal static string GetArgumentName(ExceptionArgument argument) { + Contract.Assert(Enum.IsDefined(typeof(ExceptionArgument), argument), + "The enum value is not defined, please check the ExceptionArgument Enum."); + + return argument.ToString(); + } + + // + // This function will convert an ExceptionResource enum value to the resource string. + // + internal static string GetResourceName(ExceptionResource resource) { + Contract.Assert(Enum.IsDefined(typeof(ExceptionResource), resource), + "The enum value is not defined, please check the ExceptionResource Enum."); + + return resource.ToString(); + } + + } + + // + // The convention for this enum is using the argument name as the enum name + // + internal enum ExceptionArgument { + obj, + dictionary, + dictionaryCreationThreshold, + array, + info, + key, + collection, + list, + match, + converter, + queue, + stack, + capacity, + index, + startIndex, + value, + count, + arrayIndex, + name, + mode, + item, + options, + view, + sourceBytesToCopy, + action, + comparison, + offset, + newSize, + elementType, + length, + length1, + length2, + length3, + lengths, + len, + lowerBounds, + sourceArray, + destinationArray, + sourceIndex, + destinationIndex, + indices, + index1, + index2, + index3, + other, + comparer, + endIndex, + keys, + creationOptions, + timeout, + tasks, + scheduler, + continuationFunction, + millisecondsTimeout, + millisecondsDelay, + function, + exceptions, + exception, + cancellationToken, + delay, + asyncResult, + endMethod, + endFunction, + beginMethod, + continuationOptions, + continuationAction, + + } + + // + // The convention for this enum is using the resource name as the enum name + // + internal enum ExceptionResource { + Argument_ImplementIComparable, + Argument_InvalidType, + Argument_InvalidArgumentForComparison, + Argument_InvalidRegistryKeyPermissionCheck, + ArgumentOutOfRange_NeedNonNegNum, + + Arg_ArrayPlusOffTooSmall, + Arg_NonZeroLowerBound, + Arg_RankMultiDimNotSupported, + Arg_RegKeyDelHive, + Arg_RegKeyStrLenBug, + Arg_RegSetStrArrNull, + Arg_RegSetMismatchedKind, + Arg_RegSubKeyAbsent, + Arg_RegSubKeyValueAbsent, + + Argument_AddingDuplicate, + Serialization_InvalidOnDeser, + Serialization_MissingKeys, + Serialization_NullKey, + Argument_InvalidArrayType, + NotSupported_KeyCollectionSet, + NotSupported_ValueCollectionSet, + ArgumentOutOfRange_SmallCapacity, + ArgumentOutOfRange_Index, + Argument_InvalidOffLen, + Argument_ItemNotExist, + ArgumentOutOfRange_Count, + ArgumentOutOfRange_InvalidThreshold, + ArgumentOutOfRange_ListInsert, + NotSupported_ReadOnlyCollection, + InvalidOperation_CannotRemoveFromStackOrQueue, + InvalidOperation_EmptyQueue, + InvalidOperation_EnumOpCantHappen, + InvalidOperation_EnumFailedVersion, + InvalidOperation_EmptyStack, + ArgumentOutOfRange_BiggerThanCollection, + InvalidOperation_EnumNotStarted, + InvalidOperation_EnumEnded, + NotSupported_SortedListNestedWrite, + InvalidOperation_NoValue, + InvalidOperation_RegRemoveSubKey, + Security_RegistryPermission, + UnauthorizedAccess_RegistryNoWrite, + ObjectDisposed_RegKeyClosed, + NotSupported_InComparableType, + Argument_InvalidRegistryOptionsCheck, + Argument_InvalidRegistryViewCheck, + InvalidOperation_NullArray, + Arg_MustBeType, + Arg_NeedAtLeast1Rank, + ArgumentOutOfRange_HugeArrayNotSupported, + Arg_RanksAndBounds, + Arg_RankIndices, + Arg_Need1DArray, + Arg_Need2DArray, + Arg_Need3DArray, + NotSupported_FixedSizeCollection, + ArgumentException_OtherNotArrayOfCorrectLength, + Rank_MultiDimNotSupported, + InvalidOperation_IComparerFailed, + ArgumentOutOfRange_EndIndexStartIndex, + Arg_LowerBoundsMustMatch, + Arg_BogusIComparer, + Task_WaitMulti_NullTask, + Task_ThrowIfDisposed, + Task_Start_TaskCompleted, + Task_Start_Promise, + Task_Start_ContinuationTask, + Task_Start_AlreadyStarted, + Task_RunSynchronously_TaskCompleted, + Task_RunSynchronously_Continuation, + Task_RunSynchronously_Promise, + Task_RunSynchronously_AlreadyStarted, + Task_MultiTaskContinuation_NullTask, + Task_MultiTaskContinuation_EmptyTaskList, + Task_Dispose_NotCompleted, + Task_Delay_InvalidMillisecondsDelay, + Task_Delay_InvalidDelay, + Task_ctor_LRandSR, + Task_ContinueWith_NotOnAnything, + Task_ContinueWith_ESandLR, + TaskT_TransitionToFinal_AlreadyCompleted, + TaskT_ctor_SelfReplicating, + TaskCompletionSourceT_TrySetException_NullException, + TaskCompletionSourceT_TrySetException_NoExceptions, + InvalidOperation_WrongAsyncResultOrEndCalledMultiple, + + } +} + |