#if NET20 || NET30 || NET35 || !NET_4_6
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
/*============================================================
**
**
**
** Purpose: The contract class allows for expressing preconditions,
** postconditions, and object invariants about methods in source
** code for runtime checking & static analysis.
**
** Two classes (Contract and ContractHelper) are split into partial classes
** in order to share the public front for multiple platforms (this file)
** while providing separate implementation details for each platform.
**
===========================================================*/
#define DEBUG // The behavior of this contract library should be consistent regardless of build type.
using System.Collections.Generic;
using System.Runtime.ConstrainedExecution;
namespace System.Diagnostics.Contracts
{
///
/// Contains static methods for representing program contracts such as preconditions, postconditions, and invariants.
///
///
/// WARNING: A binary rewriter must be used to insert runtime enforcement of these contracts.
/// Otherwise some contracts like Ensures can only be checked statically and will not throw exceptions during runtime when contracts are violated.
/// Please note this class uses conditional compilation to help avoid easy mistakes. Defining the preprocessor
/// symbol CONTRACTS_PRECONDITIONS will include all preconditions expressed using Contract.Requires in your
/// build. The symbol CONTRACTS_FULL will include postconditions and object invariants, and requires the binary rewriter.
///
public static partial class Contract
{
///
/// In debug builds, perform a runtime check that is true.
///
/// Expression to check to always be true.
[Conditional("DEBUG")]
[Conditional("CONTRACTS_FULL")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void Assert(bool condition)
{
if (!condition)
{
ReportFailure(ContractFailureKind.Assert, null, null, null);
}
}
///
/// In debug builds, perform a runtime check that is true.
///
/// Expression to check to always be true.
/// If it is not a constant string literal, then the contract may not be understood by tools.
[Conditional("DEBUG")]
[Conditional("CONTRACTS_FULL")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void Assert(bool condition, string userMessage)
{
if (!condition)
{
ReportFailure(ContractFailureKind.Assert, userMessage, null, null);
}
}
///
/// Instructs code analysis tools to assume the expression is true even if it can not be statically proven to always be true.
///
/// Expression to assume will always be true.
///
/// At runtime this is equivalent to an .
///
[Conditional("DEBUG")]
[Conditional("CONTRACTS_FULL")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void Assume(bool condition)
{
if (!condition)
{
ReportFailure(ContractFailureKind.Assume, null, null, null);
}
}
///
/// Instructs code analysis tools to assume the expression is true even if it can not be statically proven to always be true.
///
/// Expression to assume will always be true.
/// If it is not a constant string literal, then the contract may not be understood by tools.
///
/// At runtime this is equivalent to an .
///
[Conditional("DEBUG")]
[Conditional("CONTRACTS_FULL")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void Assume(bool condition, string userMessage)
{
if (!condition)
{
ReportFailure(ContractFailureKind.Assume, userMessage, null, null);
}
}
///
/// Marker to indicate the end of the contract section of a method.
///
[Conditional("CONTRACTS_FULL")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static void EndContractBlock()
{
// Empty
}
///
/// Specifies a public contract such that the expression will be true when the enclosing method or property returns normally.
///
/// Boolean expression representing the contract. May include and .
///
/// This call must happen at the beginning of a method or property before any other code.
/// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
/// The contract rewriter must be used for runtime enforcement of this postcondition.
///
[Conditional("CONTRACTS_FULL")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void Ensures(bool condition)
{
GC.KeepAlive(condition);
AssertMustUseRewriter(ContractFailureKind.Postcondition, "Ensures");
}
///
/// Specifies a public contract such that the expression will be true when the enclosing method or property returns normally.
///
/// Boolean expression representing the contract. May include and .
/// If it is not a constant string literal, then the contract may not be understood by tools.
///
/// This call must happen at the beginning of a method or property before any other code.
/// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
/// The contract rewriter must be used for runtime enforcement of this postcondition.
///
[Conditional("CONTRACTS_FULL")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void Ensures(bool condition, string userMessage)
{
GC.KeepAlive(condition);
GC.KeepAlive(userMessage);
AssertMustUseRewriter(ContractFailureKind.Postcondition, "Ensures");
}
///
/// Specifies a contract such that if an exception of type is thrown then the expression will be true when the enclosing method or property terminates abnormally.
///
/// Type of exception related to this postcondition.
/// Boolean expression representing the contract. May include and .
///
/// This call must happen at the beginning of a method or property before any other code.
/// This contract is exposed to clients so must only reference types and members at least as visible as the enclosing method.
/// The contract rewriter must be used for runtime enforcement of this postcondition.
///
[Conditional("CONTRACTS_FULL")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void EnsuresOnThrow(bool condition)
where TException : Exception
{
GC.KeepAlive(typeof(TException));
GC.KeepAlive(condition);
AssertMustUseRewriter(ContractFailureKind.PostconditionOnException, "EnsuresOnThrow");
}
///
/// Specifies a contract such that if an exception of type is thrown then the expression will be true when the enclosing method or property terminates abnormally.
///
/// Type of exception related to this postcondition.
/// Boolean expression representing the contract. May include and .
/// If it is not a constant string literal, then the contract may not be understood by tools.
///
/// This call must happen at the beginning of a method or property before any other code.
/// This contract is exposed to clients so must only reference types and members at least as visible as the enclosing method.
/// The contract rewriter must be used for runtime enforcement of this postcondition.
///
[Conditional("CONTRACTS_FULL")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void EnsuresOnThrow(bool condition, string userMessage)
where TException : Exception
{
GC.KeepAlive(typeof(TException));
GC.KeepAlive(condition);
GC.KeepAlive(userMessage);
AssertMustUseRewriter(ContractFailureKind.PostconditionOnException, "EnsuresOnThrow");
}
///
/// Returns whether the returns true
/// for any integer starting from to - 1.
///
/// First integer to pass to .
/// One greater than the last integer to pass to .
/// Function that is evaluated from to - 1.
/// true if returns true for any integer
/// starting from to - 1.
///
[Pure]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] // Assumes predicate obeys CER rules.
public static bool Exists(int fromInclusive, int toExclusive, Predicate predicate)
{
if (fromInclusive > toExclusive)
{
throw new ArgumentException("fromInclusive must be less than or equal to toExclusive.");
}
if (predicate == null)
{
throw new ArgumentNullException("predicate");
}
EndContractBlock();
for (var i = fromInclusive; i < toExclusive; i++)
{
if (predicate(i))
{
return true;
}
}
return false;
}
///
/// Returns whether the returns true
/// for any element in the .
///
/// The type that is contained in collection.
/// The collection from which elements will be drawn from to pass to .
/// Function that is evaluated on elements from .
/// true if and only if returns true for an element in
/// .
///
[Pure]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] // Assumes predicate & collection enumerator obey CER rules.
public static bool Exists(IEnumerable collection, Predicate predicate)
{
if (collection == null)
{
throw new ArgumentNullException("collection");
}
if (predicate == null)
{
throw new ArgumentNullException("predicate");
}
EndContractBlock();
foreach (var t in collection)
{
if (predicate(t))
{
return true;
}
}
return false;
}
///
/// Returns whether the returns true
/// for all integers starting from to - 1.
///
/// First integer to pass to .
/// One greater than the last integer to pass to .
/// Function that is evaluated from to - 1.
/// true if returns true for all integers
/// starting from to - 1.
///
[Pure]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] // Assumes predicate obeys CER rules.
public static bool ForAll(int fromInclusive, int toExclusive, Predicate predicate)
{
if (fromInclusive > toExclusive)
{
throw new ArgumentException("fromInclusive must be less than or equal to toExclusive.");
}
if (predicate == null)
{
throw new ArgumentNullException("predicate");
}
EndContractBlock();
for (var i = fromInclusive; i < toExclusive; i++)
{
if (!predicate(i))
{
return false;
}
}
return true;
}
///
/// Returns whether the returns true
/// for all elements in the .
///
/// The type that is contained in collection.
/// The collection from which elements will be drawn from to pass to .
/// Function that is evaluated on elements from .
/// true if and only if returns true for all elements in
/// .
///
[Pure]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] // Assumes predicate & collection enumerator obey CER rules.
public static bool ForAll(IEnumerable collection, Predicate predicate)
{
if (collection == null)
{
throw new ArgumentNullException("collection");
}
if (predicate == null)
{
throw new ArgumentNullException("predicate");
}
EndContractBlock();
foreach (var t in collection)
{
if (!predicate(t))
{
return false;
}
}
return true;
}
///
/// Specifies a contract such that the expression will be true after every method or property on the enclosing class.
///
/// Boolean expression representing the contract.
///
/// This contact can only be specified in a dedicated invariant method declared on a class.
/// This contract is not exposed to clients so may reference members less visible as the enclosing method.
/// The contract rewriter must be used for runtime enforcement of this invariant.
///
[Conditional("CONTRACTS_FULL")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void Invariant(bool condition)
{
GC.KeepAlive(condition);
AssertMustUseRewriter(ContractFailureKind.Invariant, "Invariant");
}
///
/// Specifies a contract such that the expression will be true after every method or property on the enclosing class.
///
/// Boolean expression representing the contract.
/// If it is not a constant string literal, then the contract may not be understood by tools.
///
/// This contact can only be specified in a dedicated invariant method declared on a class.
/// This contract is not exposed to clients so may reference members less visible as the enclosing method.
/// The contract rewriter must be used for runtime enforcement of this invariant.
///
[Conditional("CONTRACTS_FULL")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void Invariant(bool condition, string userMessage)
{
GC.KeepAlive(condition);
GC.KeepAlive(userMessage);
AssertMustUseRewriter(ContractFailureKind.Invariant, "Invariant");
}
///
/// Represents the value of as it was at the start of the method or property.
///
/// Type of . This can be inferred.
/// Value to represent. This must be a field or parameter.
/// Value of at the start of the method or property.
///
/// This method can only be used within the argument to the contract.
///
[Pure]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static T OldValue(T value)
{
GC.KeepAlive(value);
return default(T);
}
///
/// Specifies a contract such that the expression must be true before the enclosing method or property is invoked.
///
/// Boolean expression representing the contract.
///
/// This call must happen at the beginning of a method or property before any other code.
/// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
/// Use this form when backward compatibility does not force you to throw a particular exception.
///
[Conditional("CONTRACTS_FULL")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void Requires(bool condition)
{
GC.KeepAlive(condition);
AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires");
}
///
/// Specifies a contract such that the expression must be true before the enclosing method or property is invoked.
///
/// Boolean expression representing the contract.
/// If it is not a constant string literal, then the contract may not be understood by tools.
///
/// This call must happen at the beginning of a method or property before any other code.
/// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
/// Use this form when backward compatibility does not force you to throw a particular exception.
///
[Conditional("CONTRACTS_FULL")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void Requires(bool condition, string userMessage)
{
GC.KeepAlive(condition);
GC.KeepAlive(userMessage);
AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires");
}
///
/// Specifies a contract such that the expression must be true before the enclosing method or property is invoked.
///
/// The exception to throw if the condition is false.
/// Boolean expression representing the contract.
///
/// This call must happen at the beginning of a method or property before any other code.
/// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
/// Use this form when you want to throw a particular exception.
///
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void Requires(bool condition)
where TException : Exception
{
GC.KeepAlive(typeof(TException));
GC.KeepAlive(condition);
AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires");
}
///
/// Specifies a contract such that the expression must be true before the enclosing method or property is invoked.
///
/// The exception to throw if the condition is false.
/// Boolean expression representing the contract.
/// If it is not a constant string literal, then the contract may not be understood by tools.
///
/// This call must happen at the beginning of a method or property before any other code.
/// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
/// Use this form when you want to throw a particular exception.
///
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void Requires(bool condition, string userMessage)
where TException : Exception
{
GC.KeepAlive(typeof(TException));
GC.KeepAlive(condition);
GC.KeepAlive(userMessage);
AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires");
}
///
/// Represents the result (a.k.a. return value) of a method or property.
///
/// Type of return value of the enclosing method or property.
/// Return value of the enclosing method or property.
///
/// This method can only be used within the argument to the contract.
///
[Pure]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static T Result()
{
return default(T);
}
///
/// Represents the final (output) value of an out parameter when returning from a method.
///
/// Type of the out parameter.
/// The out parameter.
/// The output value of the out parameter.
///
/// This method can only be used within the argument to the contract.
///
[Pure]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static T ValueAtReturn(out T value)
{
value = default(T);
return value;
}
}
}
#endif