[corlib] CoreRT System.Threading.Tasks (#6672)
[mono-project.git] / mcs / class / referencesource / mscorlib / system / throwhelper.cs
blob7fff27c00861d59a8b2b7a7a29cb776fd3fd562c
1 // ==++==
2 //
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 //
5 // ==--==
7 namespace System {
8 // This file defines an internal class used to throw exceptions in BCL code.
9 // The main purpose is to reduce code size.
10 //
11 // The old way to throw an exception generates quite a lot IL code and assembly code.
12 // Following is an example:
13 // C# source
14 // throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
15 // IL code:
16 // IL_0003: ldstr "key"
17 // IL_0008: ldstr "ArgumentNull_Key"
18 // IL_000d: call string System.Environment::GetResourceString(string)
19 // IL_0012: newobj instance void System.ArgumentNullException::.ctor(string,string)
20 // IL_0017: throw
21 // which is 21bytes in IL.
22 //
23 // So we want to get rid of the ldstr and call to Environment.GetResource in IL.
24 // In order to do that, I created two enums: ExceptionResource, ExceptionArgument to represent the
25 // argument name and resource name in a small integer. The source code will be changed to
26 // ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key, ExceptionResource.ArgumentNull_Key);
28 // The IL code will be 7 bytes.
29 // IL_0008: ldc.i4.4
30 // IL_0009: ldc.i4.4
31 // IL_000a: call void System.ThrowHelper::ThrowArgumentNullException(valuetype System.ExceptionArgument)
32 // IL_000f: ldarg.0
34 // This will also reduce the Jitted code size a lot.
36 // It is very important we do this for generic classes because we can easily generate the same code
37 // multiple times for different instantiation.
38 //
39 // <
49 using System.Runtime.CompilerServices;
50 using System.Runtime.Serialization;
51 using System.Diagnostics.Contracts;
52 using System.Collections.Generic;
54 [Pure]
55 #if MONO
56 [System.Diagnostics.StackTraceHidden]
57 #endif
58 internal static partial class ThrowHelper {
59 #if !MONO
60 internal static void ThrowArgumentOutOfRangeException() {
61 ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
63 #endif
65 internal static void ThrowWrongKeyTypeArgumentException(object key, Type targetType) {
66 throw new ArgumentException(Environment.GetResourceString("Arg_WrongType", key, targetType), "key");
69 internal static void ThrowWrongValueTypeArgumentException(object value, Type targetType) {
70 throw new ArgumentException(Environment.GetResourceString("Arg_WrongType", value, targetType), "value");
73 internal static void ThrowKeyNotFoundException() {
74 throw new System.Collections.Generic.KeyNotFoundException();
77 internal static void ThrowArgumentException(ExceptionResource resource) {
78 throw new ArgumentException(Environment.GetResourceString(GetResourceName(resource)));
81 internal static void ThrowArgumentException(ExceptionResource resource, ExceptionArgument argument) {
82 throw new ArgumentException(Environment.GetResourceString(GetResourceName(resource)), GetArgumentName(argument));
85 #if !MONO
86 internal static void ThrowArgumentNullException(ExceptionArgument argument) {
87 throw new ArgumentNullException(GetArgumentName(argument));
90 internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument) {
91 throw new ArgumentOutOfRangeException(GetArgumentName(argument));
93 #endif
95 internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource) {
97 if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
98 // Dev11 474369 quirk: Mango had an empty message string:
99 throw new ArgumentOutOfRangeException(GetArgumentName(argument), String.Empty);
100 } else {
101 throw new ArgumentOutOfRangeException(GetArgumentName(argument),
102 Environment.GetResourceString(GetResourceName(resource)));
106 internal static void ThrowInvalidOperationException(ExceptionResource resource) {
107 throw new InvalidOperationException(Environment.GetResourceString(GetResourceName(resource)));
110 internal static void ThrowSerializationException(ExceptionResource resource) {
111 throw new SerializationException(Environment.GetResourceString(GetResourceName(resource)));
114 internal static void ThrowSecurityException(ExceptionResource resource) {
115 throw new System.Security.SecurityException(Environment.GetResourceString(GetResourceName(resource)));
118 internal static void ThrowNotSupportedException(ExceptionResource resource) {
119 throw new NotSupportedException(Environment.GetResourceString(GetResourceName(resource)));
122 internal static void ThrowUnauthorizedAccessException(ExceptionResource resource) {
123 throw new UnauthorizedAccessException(Environment.GetResourceString(GetResourceName(resource)));
126 internal static void ThrowObjectDisposedException(string objectName, ExceptionResource resource) {
127 throw new ObjectDisposedException(objectName, Environment.GetResourceString(GetResourceName(resource)));
130 #if MONO
131 internal static void ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion()
133 throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
136 internal static void ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen()
138 throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
141 internal static void ThrowInvalidOperationException_InvalidOperation_EnumNotStarted()
143 throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted);
146 internal static void ThrowInvalidOperationException_InvalidOperation_EnumEnded()
148 throw new InvalidOperationException(SR.InvalidOperation_EnumEnded);
151 private static ArgumentOutOfRangeException GetArgumentOutOfRangeException(ExceptionArgument argument, string resource)
153 return new ArgumentOutOfRangeException(GetArgumentName(argument), resource);
156 internal static void ThrowArgumentOutOfRange_IndexException()
158 throw GetArgumentOutOfRangeException(ExceptionArgument.index,
159 SR.ArgumentOutOfRange_Index);
162 internal static void ThrowIndexArgumentOutOfRange_NeedNonNegNumException()
164 throw GetArgumentOutOfRangeException(ExceptionArgument.index,
165 SR.ArgumentOutOfRange_NeedNonNegNum);
168 internal static void ThrowArgumentException_Argument_InvalidArrayType()
170 throw new ArgumentException(SR.Argument_InvalidArrayType);
173 private static ArgumentException GetAddingDuplicateWithKeyArgumentException(object key)
175 return new ArgumentException(SR.Format(SR.Argument_AddingDuplicate, key));
177 internal static void ThrowAddingDuplicateWithKeyArgumentException(object key)
179 throw GetAddingDuplicateWithKeyArgumentException(key);
182 private static KeyNotFoundException GetKeyNotFoundException(object key)
184 throw new KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, key.ToString()));
186 internal static void ThrowKeyNotFoundException(object key)
188 throw GetKeyNotFoundException(key);
190 #endif
192 // Allow nulls for reference types and Nullable<U>, but not for value types.
193 internal static void IfNullAndNullsAreIllegalThenThrow<T>(object value, ExceptionArgument argName) {
194 // Note that default(T) is not equal to null for value types except when T is Nullable<U>.
195 if (value == null && !(default(T) == null))
196 ThrowHelper.ThrowArgumentNullException(argName);
200 // This function will convert an ExceptionArgument enum value to the argument name string.
202 internal static string GetArgumentName(ExceptionArgument argument) {
203 string argumentName = null;
205 switch (argument) {
206 case ExceptionArgument.array:
207 argumentName = "array";
208 break;
210 case ExceptionArgument.arrayIndex:
211 argumentName = "arrayIndex";
212 break;
214 case ExceptionArgument.capacity:
215 argumentName = "capacity";
216 break;
218 case ExceptionArgument.collection:
219 argumentName = "collection";
220 break;
222 case ExceptionArgument.list:
223 argumentName = "list";
224 break;
226 case ExceptionArgument.converter:
227 argumentName = "converter";
228 break;
230 case ExceptionArgument.count:
231 argumentName = "count";
232 break;
234 case ExceptionArgument.dictionary:
235 argumentName = "dictionary";
236 break;
238 case ExceptionArgument.dictionaryCreationThreshold:
239 argumentName = "dictionaryCreationThreshold";
240 break;
242 case ExceptionArgument.index:
243 argumentName = "index";
244 break;
246 case ExceptionArgument.info:
247 argumentName = "info";
248 break;
250 case ExceptionArgument.key:
251 argumentName = "key";
252 break;
254 case ExceptionArgument.match:
255 argumentName = "match";
256 break;
258 case ExceptionArgument.obj:
259 argumentName = "obj";
260 break;
262 case ExceptionArgument.queue:
263 argumentName = "queue";
264 break;
266 case ExceptionArgument.stack:
267 argumentName = "stack";
268 break;
270 case ExceptionArgument.startIndex:
271 argumentName = "startIndex";
272 break;
274 case ExceptionArgument.value:
275 argumentName = "value";
276 break;
278 case ExceptionArgument.name:
279 argumentName = "name";
280 break;
282 case ExceptionArgument.mode:
283 argumentName = "mode";
284 break;
286 case ExceptionArgument.item:
287 argumentName = "item";
288 break;
290 case ExceptionArgument.options:
291 argumentName = "options";
292 break;
294 case ExceptionArgument.view:
295 argumentName = "view";
296 break;
298 case ExceptionArgument.sourceBytesToCopy:
299 argumentName = "sourceBytesToCopy";
300 break;
302 default:
303 Contract.Assert(false, "The enum value is not defined, please checked ExceptionArgumentName Enum.");
304 return string.Empty;
307 return argumentName;
311 // This function will convert an ExceptionResource enum value to the resource string.
313 internal static string GetResourceName(ExceptionResource resource) {
314 string resourceName = null;
316 switch (resource) {
317 case ExceptionResource.Argument_ImplementIComparable:
318 resourceName = "Argument_ImplementIComparable";
319 break;
321 case ExceptionResource.Argument_AddingDuplicate:
322 resourceName = "Argument_AddingDuplicate";
323 break;
325 case ExceptionResource.ArgumentOutOfRange_BiggerThanCollection:
326 resourceName = "ArgumentOutOfRange_BiggerThanCollection";
327 break;
329 case ExceptionResource.ArgumentOutOfRange_Count:
330 resourceName = "ArgumentOutOfRange_Count";
331 break;
333 case ExceptionResource.ArgumentOutOfRange_Index:
334 resourceName = "ArgumentOutOfRange_Index";
335 break;
337 case ExceptionResource.ArgumentOutOfRange_InvalidThreshold:
338 resourceName = "ArgumentOutOfRange_InvalidThreshold";
339 break;
341 case ExceptionResource.ArgumentOutOfRange_ListInsert:
342 resourceName = "ArgumentOutOfRange_ListInsert";
343 break;
345 case ExceptionResource.ArgumentOutOfRange_NeedNonNegNum:
346 resourceName = "ArgumentOutOfRange_NeedNonNegNum";
347 break;
349 case ExceptionResource.ArgumentOutOfRange_SmallCapacity:
350 resourceName = "ArgumentOutOfRange_SmallCapacity";
351 break;
353 case ExceptionResource.Arg_ArrayPlusOffTooSmall:
354 resourceName = "Arg_ArrayPlusOffTooSmall";
355 break;
357 case ExceptionResource.Arg_RankMultiDimNotSupported:
358 resourceName = "Arg_RankMultiDimNotSupported";
359 break;
361 case ExceptionResource.Arg_NonZeroLowerBound:
362 resourceName = "Arg_NonZeroLowerBound";
363 break;
365 case ExceptionResource.Argument_InvalidArrayType:
366 resourceName = "Argument_InvalidArrayType";
367 break;
369 case ExceptionResource.Argument_InvalidOffLen:
370 resourceName = "Argument_InvalidOffLen";
371 break;
373 case ExceptionResource.Argument_ItemNotExist:
374 resourceName = "Argument_ItemNotExist";
375 break;
377 case ExceptionResource.InvalidOperation_CannotRemoveFromStackOrQueue:
378 resourceName = "InvalidOperation_CannotRemoveFromStackOrQueue";
379 break;
381 case ExceptionResource.InvalidOperation_EmptyQueue:
382 resourceName = "InvalidOperation_EmptyQueue";
383 break;
385 case ExceptionResource.InvalidOperation_EnumOpCantHappen:
386 resourceName = "InvalidOperation_EnumOpCantHappen";
387 break;
389 case ExceptionResource.InvalidOperation_EnumFailedVersion:
390 resourceName = "InvalidOperation_EnumFailedVersion";
391 break;
393 case ExceptionResource.InvalidOperation_EmptyStack:
394 resourceName = "InvalidOperation_EmptyStack";
395 break;
397 case ExceptionResource.InvalidOperation_EnumNotStarted:
398 resourceName = "InvalidOperation_EnumNotStarted";
399 break;
401 case ExceptionResource.InvalidOperation_EnumEnded:
402 resourceName = "InvalidOperation_EnumEnded";
403 break;
405 case ExceptionResource.NotSupported_KeyCollectionSet:
406 resourceName = "NotSupported_KeyCollectionSet";
407 break;
409 case ExceptionResource.NotSupported_ReadOnlyCollection:
410 resourceName = "NotSupported_ReadOnlyCollection";
411 break;
413 case ExceptionResource.NotSupported_ValueCollectionSet:
414 resourceName = "NotSupported_ValueCollectionSet";
415 break;
418 case ExceptionResource.NotSupported_SortedListNestedWrite:
419 resourceName = "NotSupported_SortedListNestedWrite";
420 break;
423 case ExceptionResource.Serialization_InvalidOnDeser:
424 resourceName = "Serialization_InvalidOnDeser";
425 break;
427 case ExceptionResource.Serialization_MissingKeys:
428 resourceName = "Serialization_MissingKeys";
429 break;
431 case ExceptionResource.Serialization_NullKey:
432 resourceName = "Serialization_NullKey";
433 break;
435 case ExceptionResource.Argument_InvalidType:
436 resourceName = "Argument_InvalidType";
437 break;
439 case ExceptionResource.Argument_InvalidArgumentForComparison:
440 resourceName = "Argument_InvalidArgumentForComparison";
441 break;
443 case ExceptionResource.InvalidOperation_NoValue:
444 resourceName = "InvalidOperation_NoValue";
445 break;
447 case ExceptionResource.InvalidOperation_RegRemoveSubKey:
448 resourceName = "InvalidOperation_RegRemoveSubKey";
449 break;
451 case ExceptionResource.Arg_RegSubKeyAbsent:
452 resourceName = "Arg_RegSubKeyAbsent";
453 break;
455 case ExceptionResource.Arg_RegSubKeyValueAbsent:
456 resourceName = "Arg_RegSubKeyValueAbsent";
457 break;
459 case ExceptionResource.Arg_RegKeyDelHive:
460 resourceName = "Arg_RegKeyDelHive";
461 break;
463 case ExceptionResource.Security_RegistryPermission:
464 resourceName = "Security_RegistryPermission";
465 break;
467 case ExceptionResource.Arg_RegSetStrArrNull:
468 resourceName = "Arg_RegSetStrArrNull";
469 break;
471 case ExceptionResource.Arg_RegSetMismatchedKind:
472 resourceName = "Arg_RegSetMismatchedKind";
473 break;
475 case ExceptionResource.UnauthorizedAccess_RegistryNoWrite:
476 resourceName = "UnauthorizedAccess_RegistryNoWrite";
477 break;
479 case ExceptionResource.ObjectDisposed_RegKeyClosed:
480 resourceName = "ObjectDisposed_RegKeyClosed";
481 break;
483 case ExceptionResource.Arg_RegKeyStrLenBug:
484 resourceName = "Arg_RegKeyStrLenBug";
485 break;
487 case ExceptionResource.Argument_InvalidRegistryKeyPermissionCheck:
488 resourceName = "Argument_InvalidRegistryKeyPermissionCheck";
489 break;
491 case ExceptionResource.NotSupported_InComparableType:
492 resourceName = "NotSupported_InComparableType";
493 break;
495 case ExceptionResource.Argument_InvalidRegistryOptionsCheck:
496 resourceName = "Argument_InvalidRegistryOptionsCheck";
497 break;
499 case ExceptionResource.Argument_InvalidRegistryViewCheck:
500 resourceName = "Argument_InvalidRegistryViewCheck";
501 break;
503 default:
504 Contract.Assert( false, "The enum value is not defined, please checked ExceptionArgumentName Enum.");
505 return string.Empty;
508 return resourceName;
514 // The convention for this enum is using the argument name as the enum name
516 internal enum ExceptionArgument {
517 obj,
518 dictionary,
519 dictionaryCreationThreshold,
520 array,
521 info,
522 key,
523 collection,
524 list,
525 match,
526 converter,
527 queue,
528 stack,
529 capacity,
530 index,
531 startIndex,
532 value,
533 count,
534 arrayIndex,
535 name,
536 mode,
537 item,
538 options,
539 view,
540 sourceBytesToCopy,
541 #if MONO
542 start,
543 pointer,
544 ownedMemory,
545 text,
546 length,
547 comparer,
548 comparable,
549 exceptions,
550 exception
551 #endif
555 // The convention for this enum is using the resource name as the enum name
557 internal enum ExceptionResource {
558 Argument_ImplementIComparable,
559 Argument_InvalidType,
560 Argument_InvalidArgumentForComparison,
561 Argument_InvalidRegistryKeyPermissionCheck,
562 ArgumentOutOfRange_NeedNonNegNum,
564 Arg_ArrayPlusOffTooSmall,
565 Arg_NonZeroLowerBound,
566 Arg_RankMultiDimNotSupported,
567 Arg_RegKeyDelHive,
568 Arg_RegKeyStrLenBug,
569 Arg_RegSetStrArrNull,
570 Arg_RegSetMismatchedKind,
571 Arg_RegSubKeyAbsent,
572 Arg_RegSubKeyValueAbsent,
574 Argument_AddingDuplicate,
575 Serialization_InvalidOnDeser,
576 Serialization_MissingKeys,
577 Serialization_NullKey,
578 Argument_InvalidArrayType,
579 NotSupported_KeyCollectionSet,
580 NotSupported_ValueCollectionSet,
581 ArgumentOutOfRange_SmallCapacity,
582 ArgumentOutOfRange_Index,
583 Argument_InvalidOffLen,
584 Argument_ItemNotExist,
585 ArgumentOutOfRange_Count,
586 ArgumentOutOfRange_InvalidThreshold,
587 ArgumentOutOfRange_ListInsert,
588 NotSupported_ReadOnlyCollection,
589 InvalidOperation_CannotRemoveFromStackOrQueue,
590 InvalidOperation_EmptyQueue,
591 InvalidOperation_EnumOpCantHappen,
592 InvalidOperation_EnumFailedVersion,
593 InvalidOperation_EmptyStack,
594 ArgumentOutOfRange_BiggerThanCollection,
595 InvalidOperation_EnumNotStarted,
596 InvalidOperation_EnumEnded,
597 NotSupported_SortedListNestedWrite,
598 InvalidOperation_NoValue,
599 InvalidOperation_RegRemoveSubKey,
600 Security_RegistryPermission,
601 UnauthorizedAccess_RegistryNoWrite,
602 ObjectDisposed_RegKeyClosed,
603 NotSupported_InComparableType,
604 Argument_InvalidRegistryOptionsCheck,
605 Argument_InvalidRegistryViewCheck,
606 TaskT_TransitionToFinal_AlreadyCompleted,
607 TaskCompletionSourceT_TrySetException_NullException,
608 TaskCompletionSourceT_TrySetException_NoExceptions,