[corlib] System.Collections from CoreFX (#7478)
[mono-project.git] / mcs / class / referencesource / mscorlib / system / throwhelper.cs
blobd4031a2e92298864c68dc265dbad2be74e657e9f
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;
310 private static ArgumentOutOfRangeException GetArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
312 return new ArgumentOutOfRangeException(GetArgumentName(argument), resource.ToString());
315 internal static void ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index()
317 throw GetArgumentOutOfRangeException(ExceptionArgument.startIndex,
318 ExceptionResource.ArgumentOutOfRange_Index);
321 internal static void ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count()
323 throw GetArgumentOutOfRangeException(ExceptionArgument.count,
324 ExceptionResource.ArgumentOutOfRange_Count);
328 // This function will convert an ExceptionResource enum value to the resource string.
330 internal static string GetResourceName(ExceptionResource resource) {
331 string resourceName = null;
333 switch (resource) {
334 case ExceptionResource.Argument_ImplementIComparable:
335 resourceName = "Argument_ImplementIComparable";
336 break;
338 case ExceptionResource.Argument_AddingDuplicate:
339 resourceName = "Argument_AddingDuplicate";
340 break;
342 case ExceptionResource.ArgumentOutOfRange_BiggerThanCollection:
343 resourceName = "ArgumentOutOfRange_BiggerThanCollection";
344 break;
346 case ExceptionResource.ArgumentOutOfRange_Count:
347 resourceName = "ArgumentOutOfRange_Count";
348 break;
350 case ExceptionResource.ArgumentOutOfRange_Index:
351 resourceName = "ArgumentOutOfRange_Index";
352 break;
354 case ExceptionResource.ArgumentOutOfRange_InvalidThreshold:
355 resourceName = "ArgumentOutOfRange_InvalidThreshold";
356 break;
358 case ExceptionResource.ArgumentOutOfRange_ListInsert:
359 resourceName = "ArgumentOutOfRange_ListInsert";
360 break;
362 case ExceptionResource.ArgumentOutOfRange_NeedNonNegNum:
363 resourceName = "ArgumentOutOfRange_NeedNonNegNum";
364 break;
366 case ExceptionResource.ArgumentOutOfRange_SmallCapacity:
367 resourceName = "ArgumentOutOfRange_SmallCapacity";
368 break;
370 case ExceptionResource.Arg_ArrayPlusOffTooSmall:
371 resourceName = "Arg_ArrayPlusOffTooSmall";
372 break;
374 case ExceptionResource.Arg_RankMultiDimNotSupported:
375 resourceName = "Arg_RankMultiDimNotSupported";
376 break;
378 case ExceptionResource.Arg_NonZeroLowerBound:
379 resourceName = "Arg_NonZeroLowerBound";
380 break;
382 case ExceptionResource.Argument_InvalidArrayType:
383 resourceName = "Argument_InvalidArrayType";
384 break;
386 case ExceptionResource.Argument_InvalidOffLen:
387 resourceName = "Argument_InvalidOffLen";
388 break;
390 case ExceptionResource.Argument_ItemNotExist:
391 resourceName = "Argument_ItemNotExist";
392 break;
394 case ExceptionResource.InvalidOperation_CannotRemoveFromStackOrQueue:
395 resourceName = "InvalidOperation_CannotRemoveFromStackOrQueue";
396 break;
398 case ExceptionResource.InvalidOperation_EmptyQueue:
399 resourceName = "InvalidOperation_EmptyQueue";
400 break;
402 case ExceptionResource.InvalidOperation_EnumOpCantHappen:
403 resourceName = "InvalidOperation_EnumOpCantHappen";
404 break;
406 case ExceptionResource.InvalidOperation_EnumFailedVersion:
407 resourceName = "InvalidOperation_EnumFailedVersion";
408 break;
410 case ExceptionResource.InvalidOperation_EmptyStack:
411 resourceName = "InvalidOperation_EmptyStack";
412 break;
414 case ExceptionResource.InvalidOperation_EnumNotStarted:
415 resourceName = "InvalidOperation_EnumNotStarted";
416 break;
418 case ExceptionResource.InvalidOperation_EnumEnded:
419 resourceName = "InvalidOperation_EnumEnded";
420 break;
422 case ExceptionResource.NotSupported_KeyCollectionSet:
423 resourceName = "NotSupported_KeyCollectionSet";
424 break;
426 case ExceptionResource.NotSupported_ReadOnlyCollection:
427 resourceName = "NotSupported_ReadOnlyCollection";
428 break;
430 case ExceptionResource.NotSupported_ValueCollectionSet:
431 resourceName = "NotSupported_ValueCollectionSet";
432 break;
435 case ExceptionResource.NotSupported_SortedListNestedWrite:
436 resourceName = "NotSupported_SortedListNestedWrite";
437 break;
440 case ExceptionResource.Serialization_InvalidOnDeser:
441 resourceName = "Serialization_InvalidOnDeser";
442 break;
444 case ExceptionResource.Serialization_MissingKeys:
445 resourceName = "Serialization_MissingKeys";
446 break;
448 case ExceptionResource.Serialization_NullKey:
449 resourceName = "Serialization_NullKey";
450 break;
452 case ExceptionResource.Argument_InvalidType:
453 resourceName = "Argument_InvalidType";
454 break;
456 case ExceptionResource.Argument_InvalidArgumentForComparison:
457 resourceName = "Argument_InvalidArgumentForComparison";
458 break;
460 case ExceptionResource.InvalidOperation_NoValue:
461 resourceName = "InvalidOperation_NoValue";
462 break;
464 case ExceptionResource.InvalidOperation_RegRemoveSubKey:
465 resourceName = "InvalidOperation_RegRemoveSubKey";
466 break;
468 case ExceptionResource.Arg_RegSubKeyAbsent:
469 resourceName = "Arg_RegSubKeyAbsent";
470 break;
472 case ExceptionResource.Arg_RegSubKeyValueAbsent:
473 resourceName = "Arg_RegSubKeyValueAbsent";
474 break;
476 case ExceptionResource.Arg_RegKeyDelHive:
477 resourceName = "Arg_RegKeyDelHive";
478 break;
480 case ExceptionResource.Security_RegistryPermission:
481 resourceName = "Security_RegistryPermission";
482 break;
484 case ExceptionResource.Arg_RegSetStrArrNull:
485 resourceName = "Arg_RegSetStrArrNull";
486 break;
488 case ExceptionResource.Arg_RegSetMismatchedKind:
489 resourceName = "Arg_RegSetMismatchedKind";
490 break;
492 case ExceptionResource.UnauthorizedAccess_RegistryNoWrite:
493 resourceName = "UnauthorizedAccess_RegistryNoWrite";
494 break;
496 case ExceptionResource.ObjectDisposed_RegKeyClosed:
497 resourceName = "ObjectDisposed_RegKeyClosed";
498 break;
500 case ExceptionResource.Arg_RegKeyStrLenBug:
501 resourceName = "Arg_RegKeyStrLenBug";
502 break;
504 case ExceptionResource.Argument_InvalidRegistryKeyPermissionCheck:
505 resourceName = "Argument_InvalidRegistryKeyPermissionCheck";
506 break;
508 case ExceptionResource.NotSupported_InComparableType:
509 resourceName = "NotSupported_InComparableType";
510 break;
512 case ExceptionResource.Argument_InvalidRegistryOptionsCheck:
513 resourceName = "Argument_InvalidRegistryOptionsCheck";
514 break;
516 case ExceptionResource.Argument_InvalidRegistryViewCheck:
517 resourceName = "Argument_InvalidRegistryViewCheck";
518 break;
520 default:
521 Contract.Assert( false, "The enum value is not defined, please checked ExceptionArgumentName Enum.");
522 return string.Empty;
525 return resourceName;
531 // The convention for this enum is using the argument name as the enum name
533 internal enum ExceptionArgument {
534 obj,
535 dictionary,
536 dictionaryCreationThreshold,
537 array,
538 info,
539 key,
540 collection,
541 list,
542 match,
543 converter,
544 queue,
545 stack,
546 capacity,
547 index,
548 startIndex,
549 value,
550 count,
551 arrayIndex,
552 name,
553 mode,
554 item,
555 options,
556 view,
557 sourceBytesToCopy,
558 #if MONO
559 start,
560 pointer,
561 ownedMemory,
562 text,
563 length,
564 comparer,
565 comparable,
566 exceptions,
567 exception,
568 action,
569 comparison
570 #endif
574 // The convention for this enum is using the resource name as the enum name
576 internal enum ExceptionResource {
577 Argument_ImplementIComparable,
578 Argument_InvalidType,
579 Argument_InvalidArgumentForComparison,
580 Argument_InvalidRegistryKeyPermissionCheck,
581 ArgumentOutOfRange_NeedNonNegNum,
583 Arg_ArrayPlusOffTooSmall,
584 Arg_NonZeroLowerBound,
585 Arg_RankMultiDimNotSupported,
586 Arg_RegKeyDelHive,
587 Arg_RegKeyStrLenBug,
588 Arg_RegSetStrArrNull,
589 Arg_RegSetMismatchedKind,
590 Arg_RegSubKeyAbsent,
591 Arg_RegSubKeyValueAbsent,
593 Argument_AddingDuplicate,
594 Serialization_InvalidOnDeser,
595 Serialization_MissingKeys,
596 Serialization_NullKey,
597 Argument_InvalidArrayType,
598 NotSupported_KeyCollectionSet,
599 NotSupported_ValueCollectionSet,
600 ArgumentOutOfRange_SmallCapacity,
601 ArgumentOutOfRange_Index,
602 Argument_InvalidOffLen,
603 Argument_ItemNotExist,
604 ArgumentOutOfRange_Count,
605 ArgumentOutOfRange_InvalidThreshold,
606 ArgumentOutOfRange_ListInsert,
607 NotSupported_ReadOnlyCollection,
608 InvalidOperation_CannotRemoveFromStackOrQueue,
609 InvalidOperation_EmptyQueue,
610 InvalidOperation_EnumOpCantHappen,
611 InvalidOperation_EnumFailedVersion,
612 InvalidOperation_EmptyStack,
613 ArgumentOutOfRange_BiggerThanCollection,
614 InvalidOperation_EnumNotStarted,
615 InvalidOperation_EnumEnded,
616 NotSupported_SortedListNestedWrite,
617 InvalidOperation_NoValue,
618 InvalidOperation_RegRemoveSubKey,
619 Security_RegistryPermission,
620 UnauthorizedAccess_RegistryNoWrite,
621 ObjectDisposed_RegKeyClosed,
622 NotSupported_InComparableType,
623 Argument_InvalidRegistryOptionsCheck,
624 Argument_InvalidRegistryViewCheck,
625 TaskT_TransitionToFinal_AlreadyCompleted,
626 TaskCompletionSourceT_TrySetException_NullException,
627 TaskCompletionSourceT_TrySetException_NoExceptions,