2 // System.Diagnostics.Contracts.Contract.cs
5 // Miguel de Icaza (miguel@gnome.org)
7 // Copyright 2009 Novell (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 // * This is a blind implementation from specs, without any testing, so the escalation
33 // is probably broken, and so are the messages and arguments to the eventargs properties
35 // * How to plug the original condition into the Escalate method? Perhaps we need
36 // some injection for it?
38 // * The "originalException" in Escalate is nowhere used
40 // * We do not Escalate everything that needs to be, perhaps that is the role of the
41 // rewriter to call Escalate with the proper values?
43 // * I added a "new()" constraint to methods that took a TException because I needed
44 // to new the exception, but this is perhaps wrong.
46 // * Result and ValueAtReturn, I need to check what these do in .NET 4, but have not
47 // installed it yet ;-)
50 using System
.Collections
.Generic
;
52 namespace System
.Diagnostics
.Contracts
{
53 #if NET_2_1 || NET_4_0
59 static class Contract
{
61 public static event EventHandler
<ContractFailedEventArgs
> ContractFailed
;
63 static void Escalate (ContractFailureKind kind
, Exception e
, string text
, params object [] args
)
65 if (ContractFailed
!= null){
66 var ea
= new ContractFailedEventArgs (kind
, text
, "<condition>", e
?? new Exception ());
67 ContractFailed (null, ea
);
71 Console
.Error
.WriteLine ("Contract.{0}: {1}", kind
.ToString (), String
.Format (text
, args
));
74 [ConditionalAttribute("CONTRACTS_FULL")]
75 [ConditionalAttribute("DEBUG")]
76 public static void Assert (bool condition
)
80 Escalate (ContractFailureKind
.Assert
, null, "failure");
83 [ConditionalAttribute("DEBUG")]
84 [ConditionalAttribute("CONTRACTS_FULL")]
85 public static void Assert (bool condition
, string userMessage
)
90 Escalate (ContractFailureKind
.Assert
, null, userMessage
);
93 [ConditionalAttribute("DEBUG")]
94 [ConditionalAttribute("CONTRACTS_FULL")]
95 public static void Assume(bool condition
)
97 // At runtime, this behaves like assert
101 Escalate (ContractFailureKind
.Assume
, null, "failure");
104 [ConditionalAttribute("CONTRACTS_FULL")]
105 [ConditionalAttribute("DEBUG")]
106 public static void Assume (bool condition
, string userMessage
)
111 Escalate (ContractFailureKind
.Assume
, null, userMessage
);
114 [ConditionalAttribute("CONTRACTS_FULL")]
115 public static void EndContractBlock ()
117 // seems to be some kind of flag, no code generated
120 [ConditionalAttribute("CONTRACTS_FULL")]
121 public static void Ensures (bool condition
)
123 // Requires binary rewriter to work
126 [ConditionalAttribute("CONTRACTS_FULL")]
127 public static void Ensures (bool condition
, string userMessage
)
129 // Requires binary rewriter to work
132 [ConditionalAttribute("CONTRACTS_FULL")]
133 public static void EnsuresOnThrow
<TException
> (bool condition
) where TException
: Exception
135 // Requires binary rewriter to work
138 [ConditionalAttribute("CONTRACTS_FULL")]
139 public static void EnsuresOnThrow
<TException
> (bool condition
, string userMessage
) where TException
: Exception
141 // Requires binary rewriter to work
144 public static bool Exists
<T
> (IEnumerable
<T
> collection
, Predicate
<T
> predicate
)
146 if (predicate
== null)
147 throw new ArgumentNullException ("predicate");
148 if (collection
== null)
149 throw new ArgumentNullException ("collection");
151 foreach (var t
in collection
)
157 public static bool Exists (int fromInclusive
, int toExclusive
, Predicate
<int> predicate
)
159 if (predicate
== null)
160 throw new ArgumentNullException ("predicate");
161 if (toExclusive
< fromInclusive
)
162 throw new ArgumentException ("toExclusitve < fromInclusive");
164 for (int i
= fromInclusive
; i
< toExclusive
; i
++)
171 public static bool ForAll
<T
> (IEnumerable
<T
> collection
, Predicate
<T
> predicate
)
173 if (predicate
== null)
174 throw new ArgumentNullException ("predicate");
175 if (collection
== null)
176 throw new ArgumentNullException ("collection");
178 foreach (var t
in collection
)
185 public static bool ForAll (int fromInclusive
, int toExclusive
, Predicate
<int> predicate
)
187 if (predicate
== null)
188 throw new ArgumentNullException ("predicate");
189 if (toExclusive
< fromInclusive
)
190 throw new ArgumentException ("toExclusitve < fromInclusive");
192 for (int i
= fromInclusive
; i
< toExclusive
; i
++)
199 [ConditionalAttribute("CONTRACTS_FULL")]
200 public static void Invariant (bool condition
)
202 // Binary rewriter required
205 [ConditionalAttribute("CONTRACTS_FULL")]
206 public static void Invariant (bool condition
, string userMessage
)
208 // Binary rewriter required
211 static Exception
RewriterRequired ()
213 return new Exception ("The rewriter is required to use this method");
216 public static T OldValue
<T
> (T
value)
218 // This is really the binary rewriter that should kick-in
219 throw RewriterRequired ();
222 [ConditionalAttribute("CONTRACTS_FULL")]
223 [MonoTODO ("Currently throws Exception, needs to throw the proper exception")]
224 public static void Requires (bool condition
)
227 Escalate (ContractFailureKind
.Precondition
, null, "failure");
228 throw new Exception ();
232 [ConditionalAttribute("CONTRACTS_FULL")]
233 [MonoTODO ("Currently throws Exception, needs to throw the proper exception")]
234 public static void Requires (bool condition
, string userMessage
)
237 Escalate (ContractFailureKind
.Precondition
, null, userMessage
);
238 throw new Exception ();
242 public static void Requires
<TException
> (bool condition
) where TException
: Exception
, new ()
245 var e
= new TException ();
246 Escalate (ContractFailureKind
.Precondition
, e
, "failure");
251 public static void Requires
<TException
>(bool condition
, string userMessage
) where TException
: Exception
, new ()
254 var e
= new TException ();
255 Escalate (ContractFailureKind
.Precondition
, e
, userMessage
);
260 public static T Result
<T
> ()
262 throw RewriterRequired ();
265 public static T ValueAtReturn
<T
> (out T
value)
267 throw RewriterRequired ();