// This file defines an internal class used to throw exceptions in BCL code.
-// The main purpose is to reduce code size.
-//
+// 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
// 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
+// 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_000a: call void System.ThrowHelper::ThrowArgumentNullException(valuetype System.ExceptionArgument)
// IL_000f: ldarg.0
//
-// This will also reduce the Jitted code size a lot.
+// 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.
//
-// It is very important we do this for generic classes because we can easily generate the same code
-// multiple times for different instantiation.
-//
using System.Buffers;
using System.Collections.Generic;
throw new ArgumentOutOfRangeException();
}
- internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument)
- {
- throw new ArgumentOutOfRangeException(GetArgumentName(argument));
- }
-
- private static ArgumentOutOfRangeException GetArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
- {
- return new ArgumentOutOfRangeException(GetArgumentName(argument), GetResourceString(resource));
- }
- internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
- {
- throw GetArgumentOutOfRangeException(argument, resource);
- }
- internal static void ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index()
- {
- throw GetArgumentOutOfRangeException(ExceptionArgument.startIndex,
- ExceptionResource.ArgumentOutOfRange_Index);
- }
- internal static void ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count()
- {
- throw GetArgumentOutOfRangeException(ExceptionArgument.count,
- ExceptionResource.ArgumentOutOfRange_Count);
- }
-
internal static void ThrowArgumentException_DestinationTooShort()
{
throw new ArgumentException(SR.Argument_DestinationTooShort);
}
+
internal static void ThrowArgumentException_OverlapAlignmentMismatch()
{
throw new ArgumentException(SR.Argument_OverlapAlignmentMismatch);
throw GetArgumentOutOfRangeException(ExceptionArgument.index,
ExceptionResource.ArgumentOutOfRange_Index);
}
+
internal static void ThrowIndexArgumentOutOfRange_NeedNonNegNumException()
{
throw GetArgumentOutOfRangeException(ExceptionArgument.index,
ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
}
+
internal static void ThrowValueArgumentOutOfRange_NeedNonNegNumException()
{
throw GetArgumentOutOfRangeException(ExceptionArgument.value,
ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
}
- private static ArgumentException GetWrongKeyTypeArgumentException(object key, Type targetType)
+ internal static void ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum()
{
- return new ArgumentException(SR.Format(SR.Arg_WrongType, key, targetType), nameof(key));
+ throw GetArgumentOutOfRangeException(ExceptionArgument.length,
+ ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
}
- internal static void ThrowWrongKeyTypeArgumentException(object key, Type targetType)
+
+ internal static void ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index()
{
- throw GetWrongKeyTypeArgumentException(key, targetType);
+ throw GetArgumentOutOfRangeException(ExceptionArgument.startIndex,
+ ExceptionResource.ArgumentOutOfRange_Index);
}
- private static ArgumentException GetWrongValueTypeArgumentException(object value, Type targetType)
+ internal static void ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count()
{
- return new ArgumentException(SR.Format(SR.Arg_WrongType, value, targetType), nameof(value));
+ throw GetArgumentOutOfRangeException(ExceptionArgument.count,
+ ExceptionResource.ArgumentOutOfRange_Count);
}
- internal static void ThrowWrongValueTypeArgumentException(object value, Type targetType)
+
+ internal static void ThrowArgumentOutOfRangeException_ArgumentOutOfRange_Enum()
{
- throw GetWrongValueTypeArgumentException(value, targetType);
+ throw GetArgumentOutOfRangeException(ExceptionArgument.type,
+ ExceptionResource.ArgumentOutOfRange_Enum);
}
- private static ArgumentException GetAddingDuplicateWithKeyArgumentException(object key)
+ internal static void ThrowWrongKeyTypeArgumentException<T>(T key, Type targetType)
{
- return new ArgumentException(SR.Format(SR.Argument_AddingDuplicate, key));
+ // Generic key to move the boxing to the right hand side of throw
+ throw GetWrongKeyTypeArgumentException((object)key, targetType);
}
- internal static void ThrowAddingDuplicateWithKeyArgumentException(object key)
+
+ internal static void ThrowWrongValueTypeArgumentException<T>(T value, Type targetType)
{
- throw GetAddingDuplicateWithKeyArgumentException(key);
+ // Generic key to move the boxing to the right hand side of throw
+ throw GetWrongValueTypeArgumentException((object)value, targetType);
}
- private static KeyNotFoundException GetKeyNotFoundException(object key)
+ private static ArgumentException GetAddingDuplicateWithKeyArgumentException(object key)
{
- throw new KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, key.ToString()));
+ return new ArgumentException(SR.Format(SR.Argument_AddingDuplicateWithKey, key));
}
- internal static void ThrowKeyNotFoundException(object key)
+
+ internal static void ThrowAddingDuplicateWithKeyArgumentException<T>(T key)
{
- throw GetKeyNotFoundException(key);
+ // Generic key to move the boxing to the right hand side of throw
+ throw GetAddingDuplicateWithKeyArgumentException((object)key);
}
- internal static void ThrowArgumentException(ExceptionResource resource)
+ internal static void ThrowKeyNotFoundException<T>(T key)
{
- throw new ArgumentException(GetResourceString(resource));
+ // Generic key to move the boxing to the right hand side of throw
+ throw GetKeyNotFoundException((object)key);
}
- private static ArgumentException GetArgumentException(ExceptionResource resource, ExceptionArgument argument)
+ internal static void ThrowArgumentException(ExceptionResource resource)
{
- return new ArgumentException(GetResourceString(resource), GetArgumentName(argument));
+ throw GetArgumentException(resource);
}
+
internal static void ThrowArgumentException(ExceptionResource resource, ExceptionArgument argument)
{
throw GetArgumentException(resource, argument);
}
- internal static void ThrowAggregateException(List<Exception> exceptions)
+ private static ArgumentNullException GetArgumentNullException(ExceptionArgument argument)
{
- throw new AggregateException(exceptions);
+ return new ArgumentNullException(GetArgumentName(argument));
}
- internal static void ThrowArgumentException_Argument_InvalidArrayType()
+ internal static void ThrowArgumentNullException(ExceptionArgument argument)
{
- throw new ArgumentException(SR.Argument_InvalidArrayType);
+ throw GetArgumentNullException(argument);
}
- internal static void ThrowArgumentNullException(ExceptionArgument argument)
+ internal static void ThrowArgumentNullException(ExceptionResource resource)
+ {
+ throw new ArgumentNullException(GetResourceString(resource));
+ }
+
+ internal static void ThrowArgumentNullException(ExceptionArgument argument, ExceptionResource resource)
+ {
+ throw new ArgumentNullException(GetArgumentName(argument), GetResourceString(resource));
+ }
+
+ internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument)
{
- throw new ArgumentNullException(GetArgumentName(argument));
+ throw new ArgumentOutOfRangeException(GetArgumentName(argument));
+ }
+
+ internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
+ {
+ throw GetArgumentOutOfRangeException(argument, resource);
+ }
+
+ internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, int paramNumber, ExceptionResource resource)
+ {
+ throw GetArgumentOutOfRangeException(argument, paramNumber, resource);
}
internal static void ThrowInvalidOperationException(ExceptionResource resource)
{
- throw new InvalidOperationException(GetResourceString(resource));
+ throw GetInvalidOperationException(resource);
}
internal static void ThrowInvalidOperationException_OutstandingReferences()
throw new InvalidOperationException(SR.Memory_OutstandingReferences);
}
- internal static void ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion()
+ internal static void ThrowInvalidOperationException(ExceptionResource resource, Exception e)
{
- throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+ throw new InvalidOperationException(GetResourceString(resource), e);
}
- internal static void ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen()
+ internal static void ThrowSerializationException(ExceptionResource resource)
{
- throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+ throw new SerializationException(GetResourceString(resource));
+ }
+
+ internal static void ThrowSecurityException(ExceptionResource resource)
+ {
+ throw new System.Security.SecurityException(GetResourceString(resource));
+ }
+
+ internal static void ThrowRankException(ExceptionResource resource)
+ {
+ throw new RankException(GetResourceString(resource));
+ }
+
+ internal static void ThrowNotSupportedException(ExceptionResource resource)
+ {
+ throw new NotSupportedException(GetResourceString(resource));
+ }
+
+ internal static void ThrowUnauthorizedAccessException(ExceptionResource resource)
+ {
+ throw new UnauthorizedAccessException(GetResourceString(resource));
+ }
+
+ internal static void ThrowObjectDisposedException(string objectName, ExceptionResource resource)
+ {
+ throw new ObjectDisposedException(objectName, GetResourceString(resource));
+ }
+
+ internal static void ThrowObjectDisposedException(ExceptionResource resource)
+ {
+ throw new ObjectDisposedException(null, GetResourceString(resource));
+ }
+
+ internal static void ThrowNotSupportedException()
+ {
+ throw new NotSupportedException();
+ }
+
+ internal static void ThrowAggregateException(List<Exception> exceptions)
+ {
+ throw new AggregateException(exceptions);
+ }
+
+ internal static void ThrowOutOfMemoryException()
+ {
+ throw new OutOfMemoryException();
+ }
+
+ internal static void ThrowArgumentException_Argument_InvalidArrayType()
+ {
+ throw new ArgumentException(SR.Argument_InvalidArrayType);
}
internal static void ThrowInvalidOperationException_InvalidOperation_EnumNotStarted()
throw new InvalidOperationException(SR.InvalidOperation_EnumEnded);
}
+ internal static void ThrowInvalidOperationException_EnumCurrent(int index)
+ {
+ throw GetInvalidOperationException_EnumCurrent(index);
+ }
+
+ internal static void ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion()
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+ }
+
+ internal static void ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen()
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+ }
+
internal static void ThrowInvalidOperationException_InvalidOperation_NoValue()
{
throw new InvalidOperationException(SR.InvalidOperation_NoValue);
throw new InvalidOperationException(SR.InvalidOperation_ConcurrentOperationsNotSupported);
}
- internal static void ThrowSerializationException(ExceptionResource resource)
+ internal static void ThrowInvalidOperationException_HandleIsNotInitialized()
{
- throw new SerializationException(GetResourceString(resource));
+ throw new InvalidOperationException(SR.InvalidOperation_HandleIsNotInitialized);
}
- internal static void ThrowObjectDisposedException(ExceptionResource resource)
+ internal static void ThrowArraySegmentCtorValidationFailedExceptions(Array array, int offset, int count)
{
- throw new ObjectDisposedException(null, GetResourceString(resource));
+ throw GetArraySegmentCtorValidationFailedException(array, offset, count);
}
- internal static void ThrowNotSupportedException()
+ internal static void ThrowFormatException_BadFormatSpecifier()
{
- throw new NotSupportedException();
+ throw new FormatException(SR.Argument_BadFormatSpecifier);
}
- internal static void ThrowNotSupportedException(ExceptionResource resource)
+ internal static void ThrowArgumentOutOfRangeException_PrecisionTooLarge()
{
- throw new NotSupportedException(GetResourceString(resource));
+ throw new ArgumentOutOfRangeException("precision", SR.Format(SR.Argument_PrecisionTooLarge, StandardFormat.MaxPrecision));
+ }
+
+ internal static void ThrowArgumentOutOfRangeException_SymbolDoesNotFit()
+ {
+ throw new ArgumentOutOfRangeException("symbol", SR.Argument_BadFormatSpecifier);
}
private static Exception GetArraySegmentCtorValidationFailedException(Array array, int offset, int count)
Debug.Assert(array.Length - offset < count);
return new ArgumentException(SR.Argument_InvalidOffLen);
}
- internal static void ThrowArraySegmentCtorValidationFailedExceptions(Array array, int offset, int count)
+
+ private static ArgumentException GetArgumentException(ExceptionResource resource)
{
- throw GetArraySegmentCtorValidationFailedException(array, offset, count);
+ return new ArgumentException(GetResourceString(resource));
}
- internal static void ThrowFormatException_BadFormatSpecifier()
+ private static InvalidOperationException GetInvalidOperationException(ExceptionResource resource)
{
- throw new FormatException(SR.Argument_BadFormatSpecifier);
+ return new InvalidOperationException(GetResourceString(resource));
}
- internal static void ThrowArgumentOutOfRangeException_PrecisionTooLarge()
+ private static ArgumentException GetWrongKeyTypeArgumentException(object key, Type targetType)
{
- throw new ArgumentOutOfRangeException("precision", SR.Format(SR.Argument_PrecisionTooLarge, StandardFormat.MaxPrecision));
+ return new ArgumentException(SR.Format(SR.Arg_WrongType, key, targetType), nameof(key));
}
- internal static void ThrowArgumentOutOfRangeException_SymbolDoesNotFit()
+ private static ArgumentException GetWrongValueTypeArgumentException(object value, Type targetType)
{
- throw new ArgumentOutOfRangeException("symbol", SR.Argument_BadFormatSpecifier);
+ return new ArgumentException(SR.Format(SR.Arg_WrongType, value, targetType), nameof(value));
+ }
+
+ private static KeyNotFoundException GetKeyNotFoundException(object key)
+ {
+ return new KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, key.ToString()));
+ }
+
+ private static ArgumentOutOfRangeException GetArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
+ {
+ return new ArgumentOutOfRangeException(GetArgumentName(argument), GetResourceString(resource));
+ }
+
+ private static ArgumentException GetArgumentException(ExceptionResource resource, ExceptionArgument argument)
+ {
+ return new ArgumentException(GetResourceString(resource), GetArgumentName(argument));
+ }
+
+ private static ArgumentOutOfRangeException GetArgumentOutOfRangeException(ExceptionArgument argument, int paramNumber, ExceptionResource resource)
+ {
+ return new ArgumentOutOfRangeException(GetArgumentName(argument) + "[" + paramNumber.ToString() + "]", GetResourceString(resource));
+ }
+
+ private static InvalidOperationException GetInvalidOperationException_EnumCurrent(int index)
+ {
+ return new InvalidOperationException(
+ index < 0 ?
+ SR.InvalidOperation_EnumNotStarted :
+ SR.InvalidOperation_EnumEnded);
}
// Allow nulls for reference types and Nullable<U>, but not for value types.
[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>.
+ // 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);
}
+ internal static void ThrowNotSupportedExceptionIfNonNumericType<T>()
+ {
+ if (typeof(T) != typeof(byte) && typeof(T) != typeof(sbyte) &&
+ typeof(T) != typeof(short) && typeof(T) != typeof(ushort) &&
+ typeof(T) != typeof(int) && typeof(T) != typeof(uint) &&
+ typeof(T) != typeof(long) && typeof(T) != typeof(ulong) &&
+ typeof(T) != typeof(float) && typeof(T) != typeof(double))
+ {
+ throw new NotSupportedException(SR.Arg_TypeNotSupported);
+ }
+ }
+
+#if false // Reflection-based implementation does not work for CoreRT/ProjectN
+ // This function will convert an ExceptionArgument enum value to the argument name string.
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static string GetArgumentName(ExceptionArgument argument)
+ {
+ Debug.Assert(Enum.IsDefined(typeof(ExceptionArgument), argument),
+ "The enum value is not defined, please check the ExceptionArgument Enum.");
+
+ return argument.ToString();
+ }
+#endif
+
private static string GetArgumentName(ExceptionArgument argument)
{
switch (argument)
return "stateMachine";
case ExceptionArgument.timeout:
return "timeout";
+ case ExceptionArgument.type:
+ return "type";
+ case ExceptionArgument.sourceIndex:
+ return "sourceIndex";
+ case ExceptionArgument.sourceArray:
+ return "sourceArray";
+ case ExceptionArgument.destinationIndex:
+ return "destinationIndex";
+ case ExceptionArgument.destinationArray:
+ return "destinationArray";
+ case ExceptionArgument.pHandle:
+ return "pHandle";
+ case ExceptionArgument.other:
+ return "other";
+ case ExceptionArgument.newSize:
+ return "newSize";
+ case ExceptionArgument.lowerBounds:
+ return "lowerBounds";
+ case ExceptionArgument.lengths:
+ return "lengths";
+ case ExceptionArgument.len:
+ return "len";
+ case ExceptionArgument.keys:
+ return "keys";
+ case ExceptionArgument.indices:
+ return "indices";
+ case ExceptionArgument.index1:
+ return "index1";
+ case ExceptionArgument.index2:
+ return "index2";
+ case ExceptionArgument.index3:
+ return "index3";
+ case ExceptionArgument.length1:
+ return "length1";
+ case ExceptionArgument.length2:
+ return "length2";
+ case ExceptionArgument.length3:
+ return "length3";
+ case ExceptionArgument.endIndex:
+ return "endIndex";
+ case ExceptionArgument.elementType:
+ return "elementType";
+ case ExceptionArgument.arrayIndex:
+ return "arrayIndex";
default:
Debug.Fail("The enum value is not defined, please check the ExceptionArgument Enum.");
return "";
}
}
+#if false // Reflection-based implementation does not work for CoreRT/ProjectN
+ // This function will convert an ExceptionResource enum value to the resource string.
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static string GetResourceString(ExceptionResource resource)
+ {
+ Debug.Assert(Enum.IsDefined(typeof(ExceptionResource), resource),
+ "The enum value is not defined, please check the ExceptionResource Enum.");
+
+ return SR.GetResourceString(resource.ToString());
+ }
+#endif
+
private static string GetResourceString(ExceptionResource resource)
{
switch (resource)
return SR.Task_ThrowIfDisposed;
case ExceptionResource.Task_WaitMulti_NullTask:
return SR.Task_WaitMulti_NullTask;
+ case ExceptionResource.ArgumentException_OtherNotArrayOfCorrectLength:
+ return SR.ArgumentException_OtherNotArrayOfCorrectLength;
+ case ExceptionResource.ArgumentNull_SafeHandle:
+ return SR.ArgumentNull_SafeHandle;
+ case ExceptionResource.ArgumentOutOfRange_EndIndexStartIndex:
+ return SR.ArgumentOutOfRange_EndIndexStartIndex;
+ case ExceptionResource.ArgumentOutOfRange_Enum:
+ return SR.ArgumentOutOfRange_Enum;
+ case ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported:
+ return SR.ArgumentOutOfRange_HugeArrayNotSupported;
+ case ExceptionResource.Argument_AddingDuplicate:
+ return SR.Argument_AddingDuplicate;
+ case ExceptionResource.Argument_InvalidArgumentForComparison:
+ return SR.Argument_InvalidArgumentForComparison;
+ case ExceptionResource.Arg_LowerBoundsMustMatch:
+ return SR.Arg_LowerBoundsMustMatch;
+ case ExceptionResource.Arg_MustBeType:
+ return SR.Arg_MustBeType;
+ case ExceptionResource.Arg_Need1DArray:
+ return SR.Arg_Need1DArray;
+ case ExceptionResource.Arg_Need2DArray:
+ return SR.Arg_Need2DArray;
+ case ExceptionResource.Arg_Need3DArray:
+ return SR.Arg_Need3DArray;
+ case ExceptionResource.Arg_NeedAtLeast1Rank:
+ return SR.Arg_NeedAtLeast1Rank;
+ case ExceptionResource.Arg_RankIndices:
+ return SR.Arg_RankIndices;
+ case ExceptionResource.Arg_RanksAndBounds:
+ return SR.Arg_RanksAndBounds;
+ case ExceptionResource.InvalidOperation_IComparerFailed:
+ return SR.InvalidOperation_IComparerFailed;
+ case ExceptionResource.NotSupported_FixedSizeCollection:
+ return SR.NotSupported_FixedSizeCollection;
+ case ExceptionResource.Rank_MultiDimNotSupported:
+ return SR.Rank_MultiDimNotSupported;
default:
Debug.Assert(false,
"The enum value is not defined, please check the ExceptionResource Enum.");
//
// The convention for this enum is using the argument name as the enum name
- //
+ //
internal enum ExceptionArgument
{
obj,
millisecondsTimeout,
stateMachine,
timeout,
+ type,
+ sourceIndex,
+ sourceArray,
+ destinationIndex,
+ destinationArray,
+ pHandle,
+ other,
+ newSize,
+ lowerBounds,
+ lengths,
+ len,
+ keys,
+ indices,
+ index1,
+ index2,
+ index3,
+ length1,
+ length2,
+ length3,
+ endIndex,
+ elementType,
+ arrayIndex,
}
//
// The convention for this enum is using the resource name as the enum name
- //
+ //
internal enum ExceptionResource
{
ArgumentOutOfRange_Index,
Task_Dispose_NotCompleted,
Task_ThrowIfDisposed,
Task_WaitMulti_NullTask,
+ ArgumentException_OtherNotArrayOfCorrectLength,
+ ArgumentNull_SafeHandle,
+ ArgumentOutOfRange_EndIndexStartIndex,
+ ArgumentOutOfRange_Enum,
+ ArgumentOutOfRange_HugeArrayNotSupported,
+ Argument_AddingDuplicate,
+ Argument_InvalidArgumentForComparison,
+ Arg_LowerBoundsMustMatch,
+ Arg_MustBeType,
+ Arg_Need1DArray,
+ Arg_Need2DArray,
+ Arg_Need3DArray,
+ Arg_NeedAtLeast1Rank,
+ Arg_RankIndices,
+ Arg_RanksAndBounds,
+ InvalidOperation_IComparerFailed,
+ NotSupported_FixedSizeCollection,
+ Rank_MultiDimNotSupported,
}
}