Add and apply nullable attributes (dotnet/coreclr#24679)
[mono-project.git] / netcore / System.Private.CoreLib / shared / System / Diagnostics / Contracts / Contracts.cs
blobaf6c1a333fb954e48f59e8ae77c014bb51af4adc
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 /*============================================================
6 **
7 **
8 **
9 ** Purpose: The contract class allows for expressing preconditions,
10 ** postconditions, and object invariants about methods in source
11 ** code for runtime checking & static analysis.
13 ** Two classes (Contract and ContractHelper) are split into partial classes
14 ** in order to share the public front for multiple platforms (this file)
15 ** while providing separate implementation details for each platform.
17 ===========================================================*/
18 #define DEBUG // The behavior of this contract library should be consistent regardless of build type.
20 using System.Collections.Generic;
21 using System.Diagnostics.CodeAnalysis;
22 using System.Reflection;
24 namespace System.Diagnostics.Contracts
26 #region Attributes
28 /// <summary>
29 /// Methods and classes marked with this attribute can be used within calls to Contract methods. Such methods not make any visible state changes.
30 /// </summary>
31 [Conditional("CONTRACTS_FULL")]
32 [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Delegate | AttributeTargets.Class | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
33 public sealed class PureAttribute : Attribute
37 /// <summary>
38 /// Types marked with this attribute specify that a separate type contains the contracts for this type.
39 /// </summary>
40 [Conditional("CONTRACTS_FULL")]
41 [Conditional("DEBUG")]
42 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
43 public sealed class ContractClassAttribute : Attribute
45 private Type _typeWithContracts;
47 public ContractClassAttribute(Type typeContainingContracts)
49 _typeWithContracts = typeContainingContracts;
52 public Type TypeContainingContracts
54 get { return _typeWithContracts; }
58 /// <summary>
59 /// Types marked with this attribute specify that they are a contract for the type that is the argument of the constructor.
60 /// </summary>
61 [Conditional("CONTRACTS_FULL")]
62 [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
63 public sealed class ContractClassForAttribute : Attribute
65 private Type _typeIAmAContractFor;
67 public ContractClassForAttribute(Type typeContractsAreFor)
69 _typeIAmAContractFor = typeContractsAreFor;
72 public Type TypeContractsAreFor
74 get { return _typeIAmAContractFor; }
78 /// <summary>
79 /// This attribute is used to mark a method as being the invariant
80 /// method for a class. The method can have any name, but it must
81 /// return "void" and take no parameters. The body of the method
82 /// must consist solely of one or more calls to the method
83 /// Contract.Invariant. A suggested name for the method is
84 /// "ObjectInvariant".
85 /// </summary>
86 [Conditional("CONTRACTS_FULL")]
87 [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
88 public sealed class ContractInvariantMethodAttribute : Attribute
92 /// <summary>
93 /// Attribute that specifies that an assembly is a reference assembly with contracts.
94 /// </summary>
95 [AttributeUsage(AttributeTargets.Assembly)]
96 public sealed class ContractReferenceAssemblyAttribute : Attribute
100 /// <summary>
101 /// Methods (and properties) marked with this attribute can be used within calls to Contract methods, but have no runtime behavior associated with them.
102 /// </summary>
103 [Conditional("CONTRACTS_FULL")]
104 [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
105 public sealed class ContractRuntimeIgnoredAttribute : Attribute
109 /// <summary>
110 /// Instructs downstream tools whether to assume the correctness of this assembly, type or member without performing any verification or not.
111 /// Can use [ContractVerification(false)] to explicitly mark assembly, type or member as one to *not* have verification performed on it.
112 /// Most specific element found (member, type, then assembly) takes precedence.
113 /// (That is useful if downstream tools allow a user to decide which polarity is the default, unmarked case.)
114 /// </summary>
115 /// <remarks>
116 /// Apply this attribute to a type to apply to all members of the type, including nested types.
117 /// Apply this attribute to an assembly to apply to all types and members of the assembly.
118 /// Apply this attribute to a property to apply to both the getter and setter.
119 /// </remarks>
120 [Conditional("CONTRACTS_FULL")]
121 [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property)]
122 public sealed class ContractVerificationAttribute : Attribute
124 private bool _value;
126 public ContractVerificationAttribute(bool value) { _value = value; }
128 public bool Value
130 get { return _value; }
134 /// <summary>
135 /// Allows a field f to be used in the method contracts for a method m when f has less visibility than m.
136 /// For instance, if the method is public, but the field is private.
137 /// </summary>
138 [Conditional("CONTRACTS_FULL")]
139 [AttributeUsage(AttributeTargets.Field)]
140 public sealed class ContractPublicPropertyNameAttribute : Attribute
142 private string _publicName;
144 public ContractPublicPropertyNameAttribute(string name)
146 _publicName = name;
149 public string Name
151 get { return _publicName; }
155 /// <summary>
156 /// Enables factoring legacy if-then-throw into separate methods for reuse and full control over
157 /// thrown exception and arguments
158 /// </summary>
159 [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
160 [Conditional("CONTRACTS_FULL")]
161 public sealed class ContractArgumentValidatorAttribute : Attribute
165 /// <summary>
166 /// Enables writing abbreviations for contracts that get copied to other methods
167 /// </summary>
168 [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
169 [Conditional("CONTRACTS_FULL")]
170 public sealed class ContractAbbreviatorAttribute : Attribute
174 /// <summary>
175 /// Allows setting contract and tool options at assembly, type, or method granularity.
176 /// </summary>
177 [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
178 [Conditional("CONTRACTS_FULL")]
179 public sealed class ContractOptionAttribute : Attribute
181 private string _category;
182 private string _setting;
183 private bool _enabled;
184 private string? _value;
186 public ContractOptionAttribute(string category, string setting, bool enabled)
188 _category = category;
189 _setting = setting;
190 _enabled = enabled;
193 public ContractOptionAttribute(string category, string setting, string value)
195 _category = category;
196 _setting = setting;
197 _value = value;
200 public string Category
202 get { return _category; }
205 public string Setting
207 get { return _setting; }
210 public bool Enabled
212 get { return _enabled; }
215 public string? Value
217 get { return _value; }
221 #endregion Attributes
223 /// <summary>
224 /// Contains static methods for representing program contracts such as preconditions, postconditions, and invariants.
225 /// </summary>
226 /// <remarks>
227 /// WARNING: A binary rewriter must be used to insert runtime enforcement of these contracts.
228 /// Otherwise some contracts like Ensures can only be checked statically and will not throw exceptions during runtime when contracts are violated.
229 /// Please note this class uses conditional compilation to help avoid easy mistakes. Defining the preprocessor
230 /// symbol CONTRACTS_PRECONDITIONS will include all preconditions expressed using Contract.Requires in your
231 /// build. The symbol CONTRACTS_FULL will include postconditions and object invariants, and requires the binary rewriter.
232 /// </remarks>
233 public static partial class Contract
235 #region User Methods
237 #region Assume
239 /// <summary>
240 /// Instructs code analysis tools to assume the expression <paramref name="condition"/> is true even if it can not be statically proven to always be true.
241 /// </summary>
242 /// <param name="condition">Expression to assume will always be true.</param>
243 /// <remarks>
244 /// At runtime this is equivalent to an <seealso cref="System.Diagnostics.Contracts.Contract.Assert(bool)"/>.
245 /// </remarks>
246 [Pure]
247 [Conditional("DEBUG")]
248 [Conditional("CONTRACTS_FULL")]
249 public static void Assume([DoesNotReturnIf(false)] bool condition)
251 if (!condition)
253 ReportFailure(ContractFailureKind.Assume, null, null, null);
257 /// <summary>
258 /// Instructs code analysis tools to assume the expression <paramref name="condition"/> is true even if it can not be statically proven to always be true.
259 /// </summary>
260 /// <param name="condition">Expression to assume will always be true.</param>
261 /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
262 /// <remarks>
263 /// At runtime this is equivalent to an <seealso cref="System.Diagnostics.Contracts.Contract.Assert(bool)"/>.
264 /// </remarks>
265 [Pure]
266 [Conditional("DEBUG")]
267 [Conditional("CONTRACTS_FULL")]
268 public static void Assume([DoesNotReturnIf(false)] bool condition, string? userMessage)
270 if (!condition)
272 ReportFailure(ContractFailureKind.Assume, userMessage, null, null);
276 #endregion Assume
278 #region Assert
280 /// <summary>
281 /// In debug builds, perform a runtime check that <paramref name="condition"/> is true.
282 /// </summary>
283 /// <param name="condition">Expression to check to always be true.</param>
284 [Pure]
285 [Conditional("DEBUG")]
286 [Conditional("CONTRACTS_FULL")]
287 public static void Assert([DoesNotReturnIf(false)] bool condition)
289 if (!condition)
290 ReportFailure(ContractFailureKind.Assert, null, null, null);
293 /// <summary>
294 /// In debug builds, perform a runtime check that <paramref name="condition"/> is true.
295 /// </summary>
296 /// <param name="condition">Expression to check to always be true.</param>
297 /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
298 [Pure]
299 [Conditional("DEBUG")]
300 [Conditional("CONTRACTS_FULL")]
301 public static void Assert([DoesNotReturnIf(false)] bool condition, string? userMessage)
303 if (!condition)
304 ReportFailure(ContractFailureKind.Assert, userMessage, null, null);
307 #endregion Assert
309 #region Requires
311 /// <summary>
312 /// Specifies a contract such that the expression <paramref name="condition"/> must be true before the enclosing method or property is invoked.
313 /// </summary>
314 /// <param name="condition">Boolean expression representing the contract.</param>
315 /// <remarks>
316 /// This call must happen at the beginning of a method or property before any other code.
317 /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
318 /// Use this form when backward compatibility does not force you to throw a particular exception.
319 /// </remarks>
320 [Pure]
321 [Conditional("CONTRACTS_FULL")]
322 public static void Requires(bool condition)
324 AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires");
327 /// <summary>
328 /// Specifies a contract such that the expression <paramref name="condition"/> must be true before the enclosing method or property is invoked.
329 /// </summary>
330 /// <param name="condition">Boolean expression representing the contract.</param>
331 /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
332 /// <remarks>
333 /// This call must happen at the beginning of a method or property before any other code.
334 /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
335 /// Use this form when backward compatibility does not force you to throw a particular exception.
336 /// </remarks>
337 [Pure]
338 [Conditional("CONTRACTS_FULL")]
339 public static void Requires(bool condition, string? userMessage)
341 AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires");
344 /// <summary>
345 /// Specifies a contract such that the expression <paramref name="condition"/> must be true before the enclosing method or property is invoked.
346 /// </summary>
347 /// <param name="condition">Boolean expression representing the contract.</param>
348 /// <remarks>
349 /// This call must happen at the beginning of a method or property before any other code.
350 /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
351 /// Use this form when you want to throw a particular exception.
352 /// </remarks>
353 [Pure]
354 public static void Requires<TException>(bool condition) where TException : Exception
356 AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires<TException>");
359 /// <summary>
360 /// Specifies a contract such that the expression <paramref name="condition"/> must be true before the enclosing method or property is invoked.
361 /// </summary>
362 /// <param name="condition">Boolean expression representing the contract.</param>
363 /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
364 /// <remarks>
365 /// This call must happen at the beginning of a method or property before any other code.
366 /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
367 /// Use this form when you want to throw a particular exception.
368 /// </remarks>
369 [Pure]
370 public static void Requires<TException>(bool condition, string? userMessage) where TException : Exception
372 AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires<TException>");
375 #endregion Requires
377 #region Ensures
379 /// <summary>
380 /// Specifies a public contract such that the expression <paramref name="condition"/> will be true when the enclosing method or property returns normally.
381 /// </summary>
382 /// <param name="condition">Boolean expression representing the contract. May include <seealso cref="OldValue"/> and <seealso cref="Result"/>.</param>
383 /// <remarks>
384 /// This call must happen at the beginning of a method or property before any other code.
385 /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
386 /// The contract rewriter must be used for runtime enforcement of this postcondition.
387 /// </remarks>
388 [Pure]
389 [Conditional("CONTRACTS_FULL")]
390 public static void Ensures(bool condition)
392 AssertMustUseRewriter(ContractFailureKind.Postcondition, "Ensures");
395 /// <summary>
396 /// Specifies a public contract such that the expression <paramref name="condition"/> will be true when the enclosing method or property returns normally.
397 /// </summary>
398 /// <param name="condition">Boolean expression representing the contract. May include <seealso cref="OldValue"/> and <seealso cref="Result"/>.</param>
399 /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
400 /// <remarks>
401 /// This call must happen at the beginning of a method or property before any other code.
402 /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
403 /// The contract rewriter must be used for runtime enforcement of this postcondition.
404 /// </remarks>
405 [Pure]
406 [Conditional("CONTRACTS_FULL")]
407 public static void Ensures(bool condition, string? userMessage)
409 AssertMustUseRewriter(ContractFailureKind.Postcondition, "Ensures");
412 /// <summary>
413 /// Specifies a contract such that if an exception of type <typeparamref name="TException"/> is thrown then the expression <paramref name="condition"/> will be true when the enclosing method or property terminates abnormally.
414 /// </summary>
415 /// <typeparam name="TException">Type of exception related to this postcondition.</typeparam>
416 /// <param name="condition">Boolean expression representing the contract. May include <seealso cref="OldValue"/> and <seealso cref="Result"/>.</param>
417 /// <remarks>
418 /// This call must happen at the beginning of a method or property before any other code.
419 /// This contract is exposed to clients so must only reference types and members at least as visible as the enclosing method.
420 /// The contract rewriter must be used for runtime enforcement of this postcondition.
421 /// </remarks>
422 [Pure]
423 [Conditional("CONTRACTS_FULL")]
424 public static void EnsuresOnThrow<TException>(bool condition) where TException : Exception
426 AssertMustUseRewriter(ContractFailureKind.PostconditionOnException, "EnsuresOnThrow");
429 /// <summary>
430 /// Specifies a contract such that if an exception of type <typeparamref name="TException"/> is thrown then the expression <paramref name="condition"/> will be true when the enclosing method or property terminates abnormally.
431 /// </summary>
432 /// <typeparam name="TException">Type of exception related to this postcondition.</typeparam>
433 /// <param name="condition">Boolean expression representing the contract. May include <seealso cref="OldValue"/> and <seealso cref="Result"/>.</param>
434 /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
435 /// <remarks>
436 /// This call must happen at the beginning of a method or property before any other code.
437 /// This contract is exposed to clients so must only reference types and members at least as visible as the enclosing method.
438 /// The contract rewriter must be used for runtime enforcement of this postcondition.
439 /// </remarks>
440 [Pure]
441 [Conditional("CONTRACTS_FULL")]
442 public static void EnsuresOnThrow<TException>(bool condition, string? userMessage) where TException : Exception
444 AssertMustUseRewriter(ContractFailureKind.PostconditionOnException, "EnsuresOnThrow");
447 #region Old, Result, and Out Parameters
449 /// <summary>
450 /// Represents the result (a.k.a. return value) of a method or property.
451 /// </summary>
452 /// <typeparam name="T">Type of return value of the enclosing method or property.</typeparam>
453 /// <returns>Return value of the enclosing method or property.</returns>
454 /// <remarks>
455 /// This method can only be used within the argument to the <seealso cref="Ensures(bool)"/> contract.
456 /// </remarks>
457 [Pure]
458 public static T Result<T>() { return default!; }
460 /// <summary>
461 /// Represents the final (output) value of an out parameter when returning from a method.
462 /// </summary>
463 /// <typeparam name="T">Type of the out parameter.</typeparam>
464 /// <param name="value">The out parameter.</param>
465 /// <returns>The output value of the out parameter.</returns>
466 /// <remarks>
467 /// This method can only be used within the argument to the <seealso cref="Ensures(bool)"/> contract.
468 /// </remarks>
469 [Pure]
470 public static T ValueAtReturn<T>(out T value) { value = default!; return value; }
472 /// <summary>
473 /// Represents the value of <paramref name="value"/> as it was at the start of the method or property.
474 /// </summary>
475 /// <typeparam name="T">Type of <paramref name="value"/>. This can be inferred.</typeparam>
476 /// <param name="value">Value to represent. This must be a field or parameter.</param>
477 /// <returns>Value of <paramref name="value"/> at the start of the method or property.</returns>
478 /// <remarks>
479 /// This method can only be used within the argument to the <seealso cref="Ensures(bool)"/> contract.
480 /// </remarks>
481 [Pure]
482 public static T OldValue<T>(T value) { return default!; }
484 #endregion Old, Result, and Out Parameters
486 #endregion Ensures
488 #region Invariant
490 /// <summary>
491 /// Specifies a contract such that the expression <paramref name="condition"/> will be true after every method or property on the enclosing class.
492 /// </summary>
493 /// <param name="condition">Boolean expression representing the contract.</param>
494 /// <remarks>
495 /// This contact can only be specified in a dedicated invariant method declared on a class.
496 /// This contract is not exposed to clients so may reference members less visible as the enclosing method.
497 /// The contract rewriter must be used for runtime enforcement of this invariant.
498 /// </remarks>
499 [Pure]
500 [Conditional("CONTRACTS_FULL")]
501 public static void Invariant(bool condition)
503 AssertMustUseRewriter(ContractFailureKind.Invariant, "Invariant");
506 /// <summary>
507 /// Specifies a contract such that the expression <paramref name="condition"/> will be true after every method or property on the enclosing class.
508 /// </summary>
509 /// <param name="condition">Boolean expression representing the contract.</param>
510 /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
511 /// <remarks>
512 /// This contact can only be specified in a dedicated invariant method declared on a class.
513 /// This contract is not exposed to clients so may reference members less visible as the enclosing method.
514 /// The contract rewriter must be used for runtime enforcement of this invariant.
515 /// </remarks>
516 [Pure]
517 [Conditional("CONTRACTS_FULL")]
518 public static void Invariant(bool condition, string? userMessage)
520 AssertMustUseRewriter(ContractFailureKind.Invariant, "Invariant");
523 #endregion Invariant
525 #region Quantifiers
527 #region ForAll
529 /// <summary>
530 /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
531 /// for all integers starting from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.
532 /// </summary>
533 /// <param name="fromInclusive">First integer to pass to <paramref name="predicate"/>.</param>
534 /// <param name="toExclusive">One greater than the last integer to pass to <paramref name="predicate"/>.</param>
535 /// <param name="predicate">Function that is evaluated from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.</param>
536 /// <returns><c>true</c> if <paramref name="predicate"/> returns <c>true</c> for all integers
537 /// starting from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.</returns>
538 /// <seealso cref="System.Collections.Generic.List&lt;T&gt;.TrueForAll"/>
539 [Pure]
540 public static bool ForAll(int fromInclusive, int toExclusive, Predicate<int> predicate)
542 if (fromInclusive > toExclusive)
543 throw new ArgumentException(SR.Argument_ToExclusiveLessThanFromExclusive);
544 if (predicate == null)
545 throw new ArgumentNullException(nameof(predicate));
547 for (int i = fromInclusive; i < toExclusive; i++)
548 if (!predicate(i)) return false;
549 return true;
553 /// <summary>
554 /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
555 /// for all elements in the <paramref name="collection"/>.
556 /// </summary>
557 /// <param name="collection">The collection from which elements will be drawn from to pass to <paramref name="predicate"/>.</param>
558 /// <param name="predicate">Function that is evaluated on elements from <paramref name="collection"/>.</param>
559 /// <returns><c>true</c> if and only if <paramref name="predicate"/> returns <c>true</c> for all elements in
560 /// <paramref name="collection"/>.</returns>
561 /// <seealso cref="System.Collections.Generic.List&lt;T&gt;.TrueForAll"/>
562 [Pure]
563 public static bool ForAll<T>(IEnumerable<T> collection, Predicate<T> predicate)
565 if (collection == null)
566 throw new ArgumentNullException(nameof(collection));
567 if (predicate == null)
568 throw new ArgumentNullException(nameof(predicate));
570 foreach (T t in collection)
571 if (!predicate(t)) return false;
572 return true;
575 #endregion ForAll
577 #region Exists
579 /// <summary>
580 /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
581 /// for any integer starting from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.
582 /// </summary>
583 /// <param name="fromInclusive">First integer to pass to <paramref name="predicate"/>.</param>
584 /// <param name="toExclusive">One greater than the last integer to pass to <paramref name="predicate"/>.</param>
585 /// <param name="predicate">Function that is evaluated from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.</param>
586 /// <returns><c>true</c> if <paramref name="predicate"/> returns <c>true</c> for any integer
587 /// starting from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.</returns>
588 /// <seealso cref="System.Collections.Generic.List&lt;T&gt;.Exists"/>
589 [Pure]
590 public static bool Exists(int fromInclusive, int toExclusive, Predicate<int> predicate)
592 if (fromInclusive > toExclusive)
593 throw new ArgumentException(SR.Argument_ToExclusiveLessThanFromExclusive);
594 if (predicate == null)
595 throw new ArgumentNullException(nameof(predicate));
597 for (int i = fromInclusive; i < toExclusive; i++)
598 if (predicate(i)) return true;
599 return false;
602 /// <summary>
603 /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
604 /// for any element in the <paramref name="collection"/>.
605 /// </summary>
606 /// <param name="collection">The collection from which elements will be drawn from to pass to <paramref name="predicate"/>.</param>
607 /// <param name="predicate">Function that is evaluated on elements from <paramref name="collection"/>.</param>
608 /// <returns><c>true</c> if and only if <paramref name="predicate"/> returns <c>true</c> for an element in
609 /// <paramref name="collection"/>.</returns>
610 /// <seealso cref="System.Collections.Generic.List&lt;T&gt;.Exists"/>
611 [Pure]
612 public static bool Exists<T>(IEnumerable<T> collection, Predicate<T> predicate)
614 if (collection == null)
615 throw new ArgumentNullException(nameof(collection));
616 if (predicate == null)
617 throw new ArgumentNullException(nameof(predicate));
619 foreach (T t in collection)
620 if (predicate(t)) return true;
621 return false;
624 #endregion Exists
626 #endregion Quantifiers
628 #region Pointers
629 #endregion
631 #region Misc.
633 /// <summary>
634 /// Marker to indicate the end of the contract section of a method.
635 /// </summary>
636 [Conditional("CONTRACTS_FULL")]
637 public static void EndContractBlock() { }
639 #endregion
641 #endregion User Methods
643 #region Private Methods
645 /// <summary>
646 /// This method is used internally to trigger a failure indicating to the "programmer" that he is using the interface incorrectly.
647 /// It is NEVER used to indicate failure of actual contracts at runtime.
648 /// </summary>
649 private static void AssertMustUseRewriter(ContractFailureKind kind, string contractKind)
651 // For better diagnostics, report which assembly is at fault. Walk up stack and
652 // find the first non-mscorlib assembly.
653 Assembly thisAssembly = typeof(Contract).Assembly; // In case we refactor mscorlib, use Contract class instead of Object.
654 StackTrace stack = new StackTrace();
655 Assembly? probablyNotRewritten = null;
656 for (int i = 0; i < stack.FrameCount; i++)
658 Assembly? caller = stack.GetFrame(i)!.GetMethod()?.DeclaringType!.Assembly;
659 if (caller != null && caller != thisAssembly)
661 probablyNotRewritten = caller;
662 break;
666 if (probablyNotRewritten == null)
667 probablyNotRewritten = thisAssembly;
668 string? simpleName = probablyNotRewritten.GetName().Name;
669 System.Runtime.CompilerServices.ContractHelper.TriggerFailure(kind, SR.Format(SR.MustUseCCRewrite, contractKind, simpleName), null, null, null);
672 #endregion Private Methods
674 #region Failure Behavior
676 /// <summary>
677 /// Without contract rewriting, failing Assert/Assumes end up calling this method.
678 /// Code going through the contract rewriter never calls this method. Instead, the rewriter produced failures call
679 /// System.Runtime.CompilerServices.ContractHelper.RaiseContractFailedEvent, followed by
680 /// System.Runtime.CompilerServices.ContractHelper.TriggerFailure.
681 /// </summary>
682 [System.Diagnostics.DebuggerNonUserCode]
683 private static void ReportFailure(ContractFailureKind failureKind, string? userMessage, string? conditionText, Exception? innerException)
685 if (failureKind < ContractFailureKind.Precondition || failureKind > ContractFailureKind.Assume)
686 throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, failureKind), nameof(failureKind));
688 // displayMessage == null means: yes we handled it. Otherwise it is the localized failure message
689 var displayMessage = System.Runtime.CompilerServices.ContractHelper.RaiseContractFailedEvent(failureKind, userMessage, conditionText, innerException);
691 if (displayMessage == null)
692 return;
694 System.Runtime.CompilerServices.ContractHelper.TriggerFailure(failureKind, displayMessage, userMessage, conditionText, innerException);
697 /// <summary>
698 /// Allows a managed application environment such as an interactive interpreter (IronPython)
699 /// to be notified of contract failures and
700 /// potentially "handle" them, either by throwing a particular exception type, etc. If any of the
701 /// event handlers sets the Cancel flag in the ContractFailedEventArgs, then the Contract class will
702 /// not pop up an assert dialog box or trigger escalation policy. Hooking this event requires
703 /// full trust, because it will inform you of bugs in the appdomain and because the event handler
704 /// could allow you to continue execution.
705 /// </summary>
706 public static event EventHandler<ContractFailedEventArgs> ContractFailed
710 System.Runtime.CompilerServices.ContractHelper.InternalContractFailed += value;
712 remove
714 System.Runtime.CompilerServices.ContractHelper.InternalContractFailed -= value;
718 #endregion Failure Behavior
721 [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
722 public enum ContractFailureKind
724 Precondition,
725 Postcondition,
726 PostconditionOnException,
727 Invariant,
728 Assert,
729 Assume,
731 } // namespace System.Runtime.CompilerServices