Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / mscorlib / system / diagnostics / contracts / contracts.cs
blobe2fc7888f42deb8b1ef84375cf42fea72a745cf7
1 // ==++==
2 //
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 //
5 // ==--==
6 /*============================================================
7 **
8 ** Class: Contract
9 **
10 ** <OWNER>Microsoft,mbarnett</OWNER>
12 ** Purpose: The contract class allows for expressing preconditions,
13 ** postconditions, and object invariants about methods in source
14 ** code for runtime checking & static analysis.
16 ** Two classes (Contract and ContractHelper) are split into partial classes
17 ** in order to share the public front for multiple platforms (this file)
18 ** while providing separate implementation details for each platform.
20 ===========================================================*/
21 #define DEBUG // The behavior of this contract library should be consistent regardless of build type.
23 #if SILVERLIGHT
24 #define FEATURE_UNTRUSTED_CALLERS
26 #elif REDHAWK_RUNTIME
28 #elif BARTOK_RUNTIME
30 #else // CLR
31 #define FEATURE_UNTRUSTED_CALLERS
32 #define FEATURE_RELIABILITY_CONTRACTS
33 #define FEATURE_SERIALIZATION
34 #endif
36 using System;
37 using System.Collections.Generic;
38 using System.Diagnostics.CodeAnalysis;
39 using System.Diagnostics.Contracts;
41 #if FEATURE_RELIABILITY_CONTRACTS
42 using System.Runtime.ConstrainedExecution;
43 #endif
44 #if FEATURE_UNTRUSTED_CALLERS
45 using System.Security;
46 using System.Security.Permissions;
47 #endif
49 namespace System.Diagnostics.Contracts {
51 #region Attributes
53 /// <summary>
54 /// Methods and classes marked with this attribute can be used within calls to Contract methods. Such methods not make any visible state changes.
55 /// </summary>
56 [Conditional("CONTRACTS_FULL")]
57 [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Delegate | AttributeTargets.Class | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
58 public sealed class PureAttribute : Attribute
62 /// <summary>
63 /// Types marked with this attribute specify that a separate type contains the contracts for this type.
64 /// </summary>
65 [Conditional("CONTRACTS_FULL")]
66 [Conditional("DEBUG")]
67 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
68 public sealed class ContractClassAttribute : Attribute
70 private Type _typeWithContracts;
72 public ContractClassAttribute(Type typeContainingContracts)
74 _typeWithContracts = typeContainingContracts;
77 public Type TypeContainingContracts {
78 get { return _typeWithContracts; }
82 /// <summary>
83 /// Types marked with this attribute specify that they are a contract for the type that is the argument of the constructor.
84 /// </summary>
85 [Conditional("CONTRACTS_FULL")]
86 [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
87 public sealed class ContractClassForAttribute : Attribute
89 private Type _typeIAmAContractFor;
91 public ContractClassForAttribute(Type typeContractsAreFor)
93 _typeIAmAContractFor = typeContractsAreFor;
96 public Type TypeContractsAreFor {
97 get { return _typeIAmAContractFor; }
101 /// <summary>
102 /// This attribute is used to mark a method as being the invariant
103 /// method for a class. The method can have any name, but it must
104 /// return "void" and take no parameters. The body of the method
105 /// must consist solely of one or more calls to the method
106 /// Contract.Invariant. A suggested name for the method is
107 /// "ObjectInvariant".
108 /// </summary>
109 [Conditional("CONTRACTS_FULL")]
110 [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
111 public sealed class ContractInvariantMethodAttribute : Attribute
115 /// <summary>
116 /// Attribute that specifies that an assembly is a reference assembly with contracts.
117 /// </summary>
118 [AttributeUsage(AttributeTargets.Assembly)]
119 public sealed class ContractReferenceAssemblyAttribute : Attribute
123 /// <summary>
124 /// Methods (and properties) marked with this attribute can be used within calls to Contract methods, but have no runtime behavior associated with them.
125 /// </summary>
126 [Conditional("CONTRACTS_FULL")]
127 [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
128 public sealed class ContractRuntimeIgnoredAttribute : Attribute
133 #if FEATURE_SERIALIZATION
134 [Serializable]
135 #endif
136 internal enum Mutability
138 Immutable, // read-only after construction, except for lazy initialization & caches
139 // Do we need a "deeply immutable" value?
140 Mutable,
141 HasInitializationPhase, // read-only after some point.
142 // Do we need a value for mutable types with read-only wrapper subclasses?
145 // Note: This hasn't been thought through in any depth yet. Consider it experimental.
146 // We should replace this with Joe's concepts.
147 [Conditional("CONTRACTS_FULL")]
148 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
149 [SuppressMessage("Microsoft.Design", "CA1019:DefineAccessorsForAttributeArguments", Justification = "Thank you very much, but we like the names we've defined for the accessors")]
150 internal sealed class MutabilityAttribute : Attribute
152 private Mutability _mutabilityMarker;
154 public MutabilityAttribute(Mutability mutabilityMarker)
156 _mutabilityMarker = mutabilityMarker;
159 public Mutability Mutability {
160 get { return _mutabilityMarker; }
165 /// <summary>
166 /// Instructs downstream tools whether to assume the correctness of this assembly, type or member without performing any verification or not.
167 /// Can use [ContractVerification(false)] to explicitly mark assembly, type or member as one to *not* have verification performed on it.
168 /// Most specific element found (member, type, then assembly) takes precedence.
169 /// (That is useful if downstream tools allow a user to decide which polarity is the default, unmarked case.)
170 /// </summary>
171 /// <remarks>
172 /// Apply this attribute to a type to apply to all members of the type, including nested types.
173 /// Apply this attribute to an assembly to apply to all types and members of the assembly.
174 /// Apply this attribute to a property to apply to both the getter and setter.
175 /// </remarks>
176 [Conditional("CONTRACTS_FULL")]
177 [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property)]
178 public sealed class ContractVerificationAttribute : Attribute
180 private bool _value;
182 public ContractVerificationAttribute(bool value) { _value = value; }
184 public bool Value {
185 get { return _value; }
189 /// <summary>
190 /// Allows a field f to be used in the method contracts for a method m when f has less visibility than m.
191 /// For instance, if the method is public, but the field is private.
192 /// </summary>
193 [Conditional("CONTRACTS_FULL")]
194 [AttributeUsage(AttributeTargets.Field)]
195 [SuppressMessage("Microsoft.Design", "CA1019:DefineAccessorsForAttributeArguments", Justification = "Thank you very much, but we like the names we've defined for the accessors")]
196 public sealed class ContractPublicPropertyNameAttribute : Attribute
198 private String _publicName;
200 public ContractPublicPropertyNameAttribute(String name)
202 _publicName = name;
205 public String Name {
206 get { return _publicName; }
210 /// <summary>
211 /// Enables factoring legacy if-then-throw into separate methods for reuse and full control over
212 /// thrown exception and arguments
213 /// </summary>
214 [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
215 [Conditional("CONTRACTS_FULL")]
216 public sealed class ContractArgumentValidatorAttribute : Attribute
220 /// <summary>
221 /// Enables writing abbreviations for contracts that get copied to other methods
222 /// </summary>
223 [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
224 [Conditional("CONTRACTS_FULL")]
225 public sealed class ContractAbbreviatorAttribute : Attribute
229 /// <summary>
230 /// Allows setting contract and tool options at assembly, type, or method granularity.
231 /// </summary>
232 [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
233 [Conditional("CONTRACTS_FULL")]
234 public sealed class ContractOptionAttribute : Attribute
236 private String _category;
237 private String _setting;
238 private bool _enabled;
239 private String _value;
241 public ContractOptionAttribute(String category, String setting, bool enabled)
243 _category = category;
244 _setting = setting;
245 _enabled = enabled;
248 public ContractOptionAttribute(String category, String setting, String value)
250 _category = category;
251 _setting = setting;
252 _value = value;
255 public String Category {
256 get { return _category; }
259 public String Setting {
260 get { return _setting; }
263 public bool Enabled {
264 get { return _enabled; }
267 public String Value {
268 get { return _value; }
272 #endregion Attributes
274 /// <summary>
275 /// Contains static methods for representing program contracts such as preconditions, postconditions, and invariants.
276 /// </summary>
277 /// <remarks>
278 /// WARNING: A binary rewriter must be used to insert runtime enforcement of these contracts.
279 /// Otherwise some contracts like Ensures can only be checked statically and will not throw exceptions during runtime when contracts are violated.
280 /// Please note this class uses conditional compilation to help avoid easy mistakes. Defining the preprocessor
281 /// symbol CONTRACTS_PRECONDITIONS will include all preconditions expressed using Contract.Requires in your
282 /// build. The symbol CONTRACTS_FULL will include postconditions and object invariants, and requires the binary rewriter.
283 /// </remarks>
284 public static partial class Contract
286 #region User Methods
288 #region Assume
290 /// <summary>
291 /// 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.
292 /// </summary>
293 /// <param name="condition">Expression to assume will always be true.</param>
294 /// <remarks>
295 /// At runtime this is equivalent to an <seealso cref="System.Diagnostics.Contracts.Contract.Assert(bool)"/>.
296 /// </remarks>
297 [Pure]
298 [Conditional("DEBUG")]
299 [Conditional("CONTRACTS_FULL")]
300 #if FEATURE_RELIABILITY_CONTRACTS
301 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
302 #endif
303 public static void Assume(bool condition)
305 if (!condition) {
306 ReportFailure(ContractFailureKind.Assume, null, null, null);
310 /// <summary>
311 /// 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.
312 /// </summary>
313 /// <param name="condition">Expression to assume will always be true.</param>
314 /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
315 /// <remarks>
316 /// At runtime this is equivalent to an <seealso cref="System.Diagnostics.Contracts.Contract.Assert(bool)"/>.
317 /// </remarks>
318 [Pure]
319 [Conditional("DEBUG")]
320 [Conditional("CONTRACTS_FULL")]
321 #if FEATURE_RELIABILITY_CONTRACTS
322 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
323 #endif
324 public static void Assume(bool condition, String userMessage)
326 if (!condition) {
327 ReportFailure(ContractFailureKind.Assume, userMessage, null, null);
331 #endregion Assume
333 #region Assert
335 /// <summary>
336 /// In debug builds, perform a runtime check that <paramref name="condition"/> is true.
337 /// </summary>
338 /// <param name="condition">Expression to check to always be true.</param>
339 [Pure]
340 [Conditional("DEBUG")]
341 [Conditional("CONTRACTS_FULL")]
342 #if FEATURE_RELIABILITY_CONTRACTS
343 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
344 #endif
345 public static void Assert(bool condition)
347 if (!condition)
348 ReportFailure(ContractFailureKind.Assert, null, null, null);
351 /// <summary>
352 /// In debug builds, perform a runtime check that <paramref name="condition"/> is true.
353 /// </summary>
354 /// <param name="condition">Expression to check to always be true.</param>
355 /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
356 [Pure]
357 [Conditional("DEBUG")]
358 [Conditional("CONTRACTS_FULL")]
359 #if FEATURE_RELIABILITY_CONTRACTS
360 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
361 #endif
362 public static void Assert(bool condition, String userMessage)
364 if (!condition)
365 ReportFailure(ContractFailureKind.Assert, userMessage, null, null);
368 #endregion Assert
370 #region Requires
372 /// <summary>
373 /// Specifies a contract such that the expression <paramref name="condition"/> must be true before the enclosing method or property is invoked.
374 /// </summary>
375 /// <param name="condition">Boolean expression representing the contract.</param>
376 /// <remarks>
377 /// This call must happen at the beginning of a method or property before any other code.
378 /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
379 /// Use this form when backward compatibility does not force you to throw a particular exception.
380 /// </remarks>
381 [Pure]
382 [Conditional("CONTRACTS_FULL")]
383 #if FEATURE_RELIABILITY_CONTRACTS
384 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
385 #endif
386 public static void Requires(bool condition)
388 AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires");
391 /// <summary>
392 /// Specifies a contract such that the expression <paramref name="condition"/> must be true before the enclosing method or property is invoked.
393 /// </summary>
394 /// <param name="condition">Boolean expression representing the contract.</param>
395 /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
396 /// <remarks>
397 /// This call must happen at the beginning of a method or property before any other code.
398 /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
399 /// Use this form when backward compatibility does not force you to throw a particular exception.
400 /// </remarks>
401 [Pure]
402 [Conditional("CONTRACTS_FULL")]
403 #if FEATURE_RELIABILITY_CONTRACTS
404 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
405 #endif
406 public static void Requires(bool condition, String userMessage)
408 AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires");
411 /// <summary>
412 /// Specifies a contract such that the expression <paramref name="condition"/> must be true before the enclosing method or property is invoked.
413 /// </summary>
414 /// <param name="condition">Boolean expression representing the contract.</param>
415 /// <remarks>
416 /// This call must happen at the beginning of a method or property before any other code.
417 /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
418 /// Use this form when you want to throw a particular exception.
419 /// </remarks>
420 [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "condition")]
421 [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
422 [Pure]
423 #if FEATURE_RELIABILITY_CONTRACTS
424 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
425 #endif
426 public static void Requires<TException>(bool condition) where TException : Exception
428 AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires<TException>");
431 /// <summary>
432 /// Specifies a contract such that the expression <paramref name="condition"/> must be true before the enclosing method or property is invoked.
433 /// </summary>
434 /// <param name="condition">Boolean expression representing the contract.</param>
435 /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
436 /// <remarks>
437 /// This call must happen at the beginning of a method or property before any other code.
438 /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
439 /// Use this form when you want to throw a particular exception.
440 /// </remarks>
441 [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "userMessage")]
442 [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "condition")]
443 [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
444 [Pure]
445 #if FEATURE_RELIABILITY_CONTRACTS
446 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
447 #endif
448 public static void Requires<TException>(bool condition, String userMessage) where TException : Exception
450 AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires<TException>");
453 #endregion Requires
455 #region Ensures
457 /// <summary>
458 /// Specifies a public contract such that the expression <paramref name="condition"/> will be true when the enclosing method or property returns normally.
459 /// </summary>
460 /// <param name="condition">Boolean expression representing the contract. May include <seealso cref="OldValue"/> and <seealso cref="Result"/>.</param>
461 /// <remarks>
462 /// This call must happen at the beginning of a method or property before any other code.
463 /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
464 /// The contract rewriter must be used for runtime enforcement of this postcondition.
465 /// </remarks>
466 [Pure]
467 [Conditional("CONTRACTS_FULL")]
468 #if FEATURE_RELIABILITY_CONTRACTS
469 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
470 #endif
471 public static void Ensures(bool condition)
473 AssertMustUseRewriter(ContractFailureKind.Postcondition, "Ensures");
476 /// <summary>
477 /// Specifies a public contract such that the expression <paramref name="condition"/> will be true when the enclosing method or property returns normally.
478 /// </summary>
479 /// <param name="condition">Boolean expression representing the contract. May include <seealso cref="OldValue"/> and <seealso cref="Result"/>.</param>
480 /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
481 /// <remarks>
482 /// This call must happen at the beginning of a method or property before any other code.
483 /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
484 /// The contract rewriter must be used for runtime enforcement of this postcondition.
485 /// </remarks>
486 [Pure]
487 [Conditional("CONTRACTS_FULL")]
488 #if FEATURE_RELIABILITY_CONTRACTS
489 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
490 #endif
491 public static void Ensures(bool condition, String userMessage)
493 AssertMustUseRewriter(ContractFailureKind.Postcondition, "Ensures");
496 /// <summary>
497 /// 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.
498 /// </summary>
499 /// <typeparam name="TException">Type of exception related to this postcondition.</typeparam>
500 /// <param name="condition">Boolean expression representing the contract. May include <seealso cref="OldValue"/> and <seealso cref="Result"/>.</param>
501 /// <remarks>
502 /// This call must happen at the beginning of a method or property before any other code.
503 /// This contract is exposed to clients so must only reference types and members at least as visible as the enclosing method.
504 /// The contract rewriter must be used for runtime enforcement of this postcondition.
505 /// </remarks>
506 [Pure]
507 [Conditional("CONTRACTS_FULL")]
508 [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Exception type used in tools.")]
509 #if FEATURE_RELIABILITY_CONTRACTS
510 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
511 #endif
512 public static void EnsuresOnThrow<TException>(bool condition) where TException : Exception
514 AssertMustUseRewriter(ContractFailureKind.PostconditionOnException, "EnsuresOnThrow");
517 /// <summary>
518 /// 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.
519 /// </summary>
520 /// <typeparam name="TException">Type of exception related to this postcondition.</typeparam>
521 /// <param name="condition">Boolean expression representing the contract. May include <seealso cref="OldValue"/> and <seealso cref="Result"/>.</param>
522 /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
523 /// <remarks>
524 /// This call must happen at the beginning of a method or property before any other code.
525 /// This contract is exposed to clients so must only reference types and members at least as visible as the enclosing method.
526 /// The contract rewriter must be used for runtime enforcement of this postcondition.
527 /// </remarks>
528 [Pure]
529 [Conditional("CONTRACTS_FULL")]
530 [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Exception type used in tools.")]
531 #if FEATURE_RELIABILITY_CONTRACTS
532 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
533 #endif
534 public static void EnsuresOnThrow<TException>(bool condition, String userMessage) where TException : Exception
536 AssertMustUseRewriter(ContractFailureKind.PostconditionOnException, "EnsuresOnThrow");
539 #region Old, Result, and Out Parameters
541 /// <summary>
542 /// Represents the result (a.k.a. return value) of a method or property.
543 /// </summary>
544 /// <typeparam name="T">Type of return value of the enclosing method or property.</typeparam>
545 /// <returns>Return value of the enclosing method or property.</returns>
546 /// <remarks>
547 /// This method can only be used within the argument to the <seealso cref="Ensures(bool)"/> contract.
548 /// </remarks>
549 [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Not intended to be called at runtime.")]
550 [Pure]
551 #if FEATURE_RELIABILITY_CONTRACTS
552 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
553 #endif
554 public static T Result<T>() { return default(T); }
556 /// <summary>
557 /// Represents the final (output) value of an out parameter when returning from a method.
558 /// </summary>
559 /// <typeparam name="T">Type of the out parameter.</typeparam>
560 /// <param name="value">The out parameter.</param>
561 /// <returns>The output value of the out parameter.</returns>
562 /// <remarks>
563 /// This method can only be used within the argument to the <seealso cref="Ensures(bool)"/> contract.
564 /// </remarks>
565 [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "0#", Justification = "Not intended to be called at runtime.")]
566 [Pure]
567 #if FEATURE_RELIABILITY_CONTRACTS
568 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
569 #endif
570 public static T ValueAtReturn<T>(out T value) { value = default(T); return value; }
572 /// <summary>
573 /// Represents the value of <paramref name="value"/> as it was at the start of the method or property.
574 /// </summary>
575 /// <typeparam name="T">Type of <paramref name="value"/>. This can be inferred.</typeparam>
576 /// <param name="value">Value to represent. This must be a field or parameter.</param>
577 /// <returns>Value of <paramref name="value"/> at the start of the method or property.</returns>
578 /// <remarks>
579 /// This method can only be used within the argument to the <seealso cref="Ensures(bool)"/> contract.
580 /// </remarks>
581 [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "value")]
582 [Pure]
583 #if FEATURE_RELIABILITY_CONTRACTS
584 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
585 #endif
586 public static T OldValue<T>(T value) { return default(T); }
588 #endregion Old, Result, and Out Parameters
590 #endregion Ensures
592 #region Invariant
594 /// <summary>
595 /// Specifies a contract such that the expression <paramref name="condition"/> will be true after every method or property on the enclosing class.
596 /// </summary>
597 /// <param name="condition">Boolean expression representing the contract.</param>
598 /// <remarks>
599 /// This contact can only be specified in a dedicated invariant method declared on a class.
600 /// This contract is not exposed to clients so may reference members less visible as the enclosing method.
601 /// The contract rewriter must be used for runtime enforcement of this invariant.
602 /// </remarks>
603 [Pure]
604 [Conditional("CONTRACTS_FULL")]
605 #if FEATURE_RELIABILITY_CONTRACTS
606 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
607 #endif
608 public static void Invariant(bool condition)
610 AssertMustUseRewriter(ContractFailureKind.Invariant, "Invariant");
613 /// <summary>
614 /// Specifies a contract such that the expression <paramref name="condition"/> will be true after every method or property on the enclosing class.
615 /// </summary>
616 /// <param name="condition">Boolean expression representing the contract.</param>
617 /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
618 /// <remarks>
619 /// This contact can only be specified in a dedicated invariant method declared on a class.
620 /// This contract is not exposed to clients so may reference members less visible as the enclosing method.
621 /// The contract rewriter must be used for runtime enforcement of this invariant.
622 /// </remarks>
623 [Pure]
624 [Conditional("CONTRACTS_FULL")]
625 #if FEATURE_RELIABILITY_CONTRACTS
626 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
627 #endif
628 public static void Invariant(bool condition, String userMessage)
630 AssertMustUseRewriter(ContractFailureKind.Invariant, "Invariant");
633 #endregion Invariant
635 #region Quantifiers
637 #region ForAll
639 /// <summary>
640 /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
641 /// for all integers starting from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.
642 /// </summary>
643 /// <param name="fromInclusive">First integer to pass to <paramref name="predicate"/>.</param>
644 /// <param name="toExclusive">One greater than the last integer to pass to <paramref name="predicate"/>.</param>
645 /// <param name="predicate">Function that is evaluated from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.</param>
646 /// <returns><c>true</c> if <paramref name="predicate"/> returns <c>true</c> for all integers
647 /// starting from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.</returns>
648 /// <seealso cref="System.Collections.Generic.List&lt;T&gt;.TrueForAll"/>
649 [Pure]
650 #if FEATURE_RELIABILITY_CONTRACTS
651 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] // Assumes predicate obeys CER rules.
652 #endif
653 public static bool ForAll(int fromInclusive, int toExclusive, Predicate<int> predicate)
655 if (fromInclusive > toExclusive)
656 #if INSIDE_CLR
657 throw new ArgumentException(Environment.GetResourceString("Argument_ToExclusiveLessThanFromExclusive"));
658 #else
659 throw new ArgumentException("fromInclusive must be less than or equal to toExclusive.");
660 #endif
661 if (predicate == null)
662 throw new ArgumentNullException("predicate");
663 Contract.EndContractBlock();
665 for (int i = fromInclusive; i < toExclusive; i++)
666 if (!predicate(i)) return false;
667 return true;
671 /// <summary>
672 /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
673 /// for all elements in the <paramref name="collection"/>.
674 /// </summary>
675 /// <param name="collection">The collection from which elements will be drawn from to pass to <paramref name="predicate"/>.</param>
676 /// <param name="predicate">Function that is evaluated on elements from <paramref name="collection"/>.</param>
677 /// <returns><c>true</c> if and only if <paramref name="predicate"/> returns <c>true</c> for all elements in
678 /// <paramref name="collection"/>.</returns>
679 /// <seealso cref="System.Collections.Generic.List&lt;T&gt;.TrueForAll"/>
680 [Pure]
681 #if FEATURE_RELIABILITY_CONTRACTS
682 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] // Assumes predicate & collection enumerator obey CER rules.
683 #endif
684 public static bool ForAll<T>(IEnumerable<T> collection, Predicate<T> predicate)
686 if (collection == null)
687 throw new ArgumentNullException("collection");
688 if (predicate == null)
689 throw new ArgumentNullException("predicate");
690 Contract.EndContractBlock();
692 foreach (T t in collection)
693 if (!predicate(t)) return false;
694 return true;
697 #endregion ForAll
699 #region Exists
701 /// <summary>
702 /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
703 /// for any integer starting from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.
704 /// </summary>
705 /// <param name="fromInclusive">First integer to pass to <paramref name="predicate"/>.</param>
706 /// <param name="toExclusive">One greater than the last integer to pass to <paramref name="predicate"/>.</param>
707 /// <param name="predicate">Function that is evaluated from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.</param>
708 /// <returns><c>true</c> if <paramref name="predicate"/> returns <c>true</c> for any integer
709 /// starting from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.</returns>
710 /// <seealso cref="System.Collections.Generic.List&lt;T&gt;.Exists"/>
711 [Pure]
712 #if FEATURE_RELIABILITY_CONTRACTS
713 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] // Assumes predicate obeys CER rules.
714 #endif
715 public static bool Exists(int fromInclusive, int toExclusive, Predicate<int> predicate)
717 if (fromInclusive > toExclusive)
718 #if INSIDE_CLR
719 throw new ArgumentException(Environment.GetResourceString("Argument_ToExclusiveLessThanFromExclusive"));
720 #else
721 throw new ArgumentException("fromInclusive must be less than or equal to toExclusive.");
722 #endif
723 if (predicate == null)
724 throw new ArgumentNullException("predicate");
725 Contract.EndContractBlock();
727 for (int i = fromInclusive; i < toExclusive; i++)
728 if (predicate(i)) return true;
729 return false;
732 /// <summary>
733 /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
734 /// for any element in the <paramref name="collection"/>.
735 /// </summary>
736 /// <param name="collection">The collection from which elements will be drawn from to pass to <paramref name="predicate"/>.</param>
737 /// <param name="predicate">Function that is evaluated on elements from <paramref name="collection"/>.</param>
738 /// <returns><c>true</c> if and only if <paramref name="predicate"/> returns <c>true</c> for an element in
739 /// <paramref name="collection"/>.</returns>
740 /// <seealso cref="System.Collections.Generic.List&lt;T&gt;.Exists"/>
741 [Pure]
742 #if FEATURE_RELIABILITY_CONTRACTS
743 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] // Assumes predicate & collection enumerator obey CER rules.
744 #endif
745 public static bool Exists<T>(IEnumerable<T> collection, Predicate<T> predicate)
747 if (collection == null)
748 throw new ArgumentNullException("collection");
749 if (predicate == null)
750 throw new ArgumentNullException("predicate");
751 Contract.EndContractBlock();
753 foreach (T t in collection)
754 if (predicate(t)) return true;
755 return false;
758 #endregion Exists
760 #endregion Quantifiers
762 #region Pointers
763 // @
764 #if FEATURE_UNSAFE_CONTRACTS
765 /// <summary>
766 /// Runtime checking for pointer bounds is not currently feasible. Thus, at runtime, we just return
767 /// a very long extent for each pointer that is writable. As long as assertions are of the form
768 /// WritableBytes(ptr) >= ..., the runtime assertions will not fail.
769 /// The runtime value is 2^64 - 1 or 2^32 - 1.
770 /// </summary>
771 [SuppressMessage("Microsoft.Performance", "CA1802", Justification = "FxCop is confused")]
772 static readonly ulong MaxWritableExtent = (UIntPtr.Size == 4) ? UInt32.MaxValue : UInt64.MaxValue;
774 /// <summary>
775 /// Allows specifying a writable extent for a UIntPtr, similar to SAL's writable extent.
776 /// NOTE: this is for static checking only. No useful runtime code can be generated for this
777 /// at the moment.
778 /// </summary>
779 /// <param name="startAddress">Start of memory region</param>
780 /// <returns>The result is the number of bytes writable starting at <paramref name="startAddress"/></returns>
781 [CLSCompliant(false)]
782 [Pure]
783 [ContractRuntimeIgnored]
784 #if FEATURE_RELIABILITY_CONTRACTS
785 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
786 #endif
787 public static ulong WritableBytes(UIntPtr startAddress) { return MaxWritableExtent - startAddress.ToUInt64(); }
789 /// <summary>
790 /// Allows specifying a writable extent for a UIntPtr, similar to SAL's writable extent.
791 /// NOTE: this is for static checking only. No useful runtime code can be generated for this
792 /// at the moment.
793 /// </summary>
794 /// <param name="startAddress">Start of memory region</param>
795 /// <returns>The result is the number of bytes writable starting at <paramref name="startAddress"/></returns>
796 [CLSCompliant(false)]
797 [Pure]
798 [ContractRuntimeIgnored]
799 #if FEATURE_RELIABILITY_CONTRACTS
800 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
801 #endif
802 public static ulong WritableBytes(IntPtr startAddress) { return MaxWritableExtent - (ulong)startAddress; }
804 /// <summary>
805 /// Allows specifying a writable extent for a UIntPtr, similar to SAL's writable extent.
806 /// NOTE: this is for static checking only. No useful runtime code can be generated for this
807 /// at the moment.
808 /// </summary>
809 /// <param name="startAddress">Start of memory region</param>
810 /// <returns>The result is the number of bytes writable starting at <paramref name="startAddress"/></returns>
811 [CLSCompliant(false)]
812 [Pure]
813 [ContractRuntimeIgnored]
814 [SecurityCritical]
815 #if FEATURE_RELIABILITY_CONTRACTS
816 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
817 #endif
820 unsafe public static ulong WritableBytes(void* startAddress) { return MaxWritableExtent - (ulong)startAddress; }
822 /// <summary>
823 /// Allows specifying a readable extent for a UIntPtr, similar to SAL's readable extent.
824 /// NOTE: this is for static checking only. No useful runtime code can be generated for this
825 /// at the moment.
826 /// </summary>
827 /// <param name="startAddress">Start of memory region</param>
828 /// <returns>The result is the number of bytes readable starting at <paramref name="startAddress"/></returns>
829 [CLSCompliant(false)]
830 [Pure]
831 [ContractRuntimeIgnored]
832 #if FEATURE_RELIABILITY_CONTRACTS
833 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
834 #endif
835 public static ulong ReadableBytes(UIntPtr startAddress) { return MaxWritableExtent - startAddress.ToUInt64(); }
837 /// <summary>
838 /// Allows specifying a readable extent for a UIntPtr, similar to SAL's readable extent.
839 /// NOTE: this is for static checking only. No useful runtime code can be generated for this
840 /// at the moment.
841 /// </summary>
842 /// <param name="startAddress">Start of memory region</param>
843 /// <returns>The result is the number of bytes readable starting at <paramref name="startAddress"/></returns>
844 [CLSCompliant(false)]
845 [Pure]
846 [ContractRuntimeIgnored]
847 #if FEATURE_RELIABILITY_CONTRACTS
848 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
849 #endif
850 public static ulong ReadableBytes(IntPtr startAddress) { return MaxWritableExtent - (ulong)startAddress; }
852 /// <summary>
853 /// Allows specifying a readable extent for a UIntPtr, similar to SAL's readable extent.
854 /// NOTE: this is for static checking only. No useful runtime code can be generated for this
855 /// at the moment.
856 /// </summary>
857 /// <param name="startAddress">Start of memory region</param>
858 /// <returns>The result is the number of bytes readable starting at <paramref name="startAddress"/></returns>
859 [CLSCompliant(false)]
860 [Pure]
861 [ContractRuntimeIgnored]
862 [SecurityCritical]
863 #if FEATURE_RELIABILITY_CONTRACTS
864 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
865 #endif
866 unsafe public static ulong ReadableBytes(void* startAddress) { return MaxWritableExtent - (ulong)startAddress; }
867 #endif // FEATURE_UNSAFE_CONTRACTS
868 #endregion
870 #region Misc.
872 /// <summary>
873 /// Marker to indicate the end of the contract section of a method.
874 /// </summary>
875 [Conditional("CONTRACTS_FULL")]
876 #if FEATURE_RELIABILITY_CONTRACTS
877 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
878 #endif
879 public static void EndContractBlock() { }
881 #endregion
883 #endregion User Methods
885 #region Failure Behavior
887 /// <summary>
888 /// Without contract rewriting, failing Assert/Assumes end up calling this method.
889 /// Code going through the contract rewriter never calls this method. Instead, the rewriter produced failures call
890 /// System.Runtime.CompilerServices.ContractHelper.RaiseContractFailedEvent, followed by
891 /// System.Runtime.CompilerServices.ContractHelper.TriggerFailure.
892 /// </summary>
893 static partial void ReportFailure(ContractFailureKind failureKind, String userMessage, String conditionText, Exception innerException);
895 /// <summary>
896 /// This method is used internally to trigger a failure indicating to the "programmer" that he is using the interface incorrectly.
897 /// It is NEVER used to indicate failure of actual contracts at runtime.
898 /// </summary>
899 static partial void AssertMustUseRewriter(ContractFailureKind kind, String contractKind);
901 #endregion
904 public enum ContractFailureKind {
905 Precondition,
906 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Postcondition")]
907 Postcondition,
908 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Postcondition")]
909 PostconditionOnException,
910 Invariant,
911 Assert,
912 Assume,
918 // Note: In .NET FX 4.5, we duplicated the ContractHelper class in the System.Runtime.CompilerServices
919 // namespace to remove an ugly wart of a namespace from the Windows 8 profile. But we still need the
920 // old locations left around, so we can support rewritten .NET FX 4.0 libraries. Consider removing
921 // these from our reference assembly in a future version.
922 namespace System.Diagnostics.Contracts.Internal
924 [Obsolete("Use the ContractHelper class in the System.Runtime.CompilerServices namespace instead.")]
925 public static class ContractHelper
927 #region Rewriter Failure Hooks
929 /// <summary>
930 /// Rewriter will call this method on a contract failure to allow listeners to be notified.
931 /// The method should not perform any failure (assert/throw) itself.
932 /// </summary>
933 /// <returns>null if the event was handled and should not trigger a failure.
934 /// Otherwise, returns the localized failure message</returns>
935 [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate")]
936 [System.Diagnostics.DebuggerNonUserCode]
937 #if FEATURE_RELIABILITY_CONTRACTS
938 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
939 #endif
940 public static string RaiseContractFailedEvent(ContractFailureKind failureKind, String userMessage, String conditionText, Exception innerException)
942 return System.Runtime.CompilerServices.ContractHelper.RaiseContractFailedEvent(failureKind, userMessage, conditionText, innerException);
945 /// <summary>
946 /// Rewriter calls this method to get the default failure behavior.
947 /// </summary>
948 [System.Diagnostics.DebuggerNonUserCode]
949 #if FEATURE_RELIABILITY_CONTRACTS
950 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
951 #endif
952 public static void TriggerFailure(ContractFailureKind kind, String displayMessage, String userMessage, String conditionText, Exception innerException)
954 System.Runtime.CompilerServices.ContractHelper.TriggerFailure(kind, displayMessage, userMessage, conditionText, innerException);
957 #endregion Rewriter Failure Hooks
959 } // namespace System.Diagnostics.Contracts.Internal
962 namespace System.Runtime.CompilerServices
964 public static partial class ContractHelper
966 #region Rewriter Failure Hooks
968 /// <summary>
969 /// Rewriter will call this method on a contract failure to allow listeners to be notified.
970 /// The method should not perform any failure (assert/throw) itself.
971 /// </summary>
972 /// <returns>null if the event was handled and should not trigger a failure.
973 /// Otherwise, returns the localized failure message</returns>
974 [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate")]
975 [System.Diagnostics.DebuggerNonUserCode]
976 #if FEATURE_RELIABILITY_CONTRACTS
977 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
978 #endif
979 public static string RaiseContractFailedEvent(ContractFailureKind failureKind, String userMessage, String conditionText, Exception innerException)
981 var resultFailureMessage = "Contract failed"; // default in case implementation does not assign anything.
982 RaiseContractFailedEventImplementation(failureKind, userMessage, conditionText, innerException, ref resultFailureMessage);
983 return resultFailureMessage;
987 /// <summary>
988 /// Rewriter calls this method to get the default failure behavior.
989 /// </summary>
990 [System.Diagnostics.DebuggerNonUserCode]
991 #if FEATURE_RELIABILITY_CONTRACTS
992 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
993 #endif
994 public static void TriggerFailure(ContractFailureKind kind, String displayMessage, String userMessage, String conditionText, Exception innerException)
996 TriggerFailureImplementation(kind, displayMessage, userMessage, conditionText, innerException);
999 #endregion Rewriter Failure Hooks
1001 #region Implementation Stubs
1003 /// <summary>
1004 /// Rewriter will call this method on a contract failure to allow listeners to be notified.
1005 /// The method should not perform any failure (assert/throw) itself.
1006 /// This method has 3 functions:
1007 /// 1. Call any contract hooks (such as listeners to Contract failed events)
1008 /// 2. Determine if the listeneres deem the failure as handled (then resultFailureMessage should be set to null)
1009 /// 3. Produce a localized resultFailureMessage used in advertising the failure subsequently.
1010 /// </summary>
1011 /// <param name="resultFailureMessage">Should really be out (or the return value), but partial methods are not flexible enough.
1012 /// On exit: null if the event was handled and should not trigger a failure.
1013 /// Otherwise, returns the localized failure message</param>
1014 static partial void RaiseContractFailedEventImplementation(ContractFailureKind failureKind, String userMessage, String conditionText, Exception innerException, ref string resultFailureMessage);
1016 /// <summary>
1017 /// Implements the default failure behavior of the platform. Under the BCL, it triggers an Assert box.
1018 /// </summary>
1019 static partial void TriggerFailureImplementation(ContractFailureKind kind, String displayMessage, String userMessage, String conditionText, Exception innerException);
1021 #endregion Implementation Stubs
1023 } // namespace System.Runtime.CompilerServices