2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / corlib / System.Diagnostics.Contracts / Contract.cs
bloba046e186d1e672a19109158b1b4dd548da19e698
1 //
2 // System.Diagnostics.Contracts.Contract.cs
3 //
4 // Authors:
5 // Miguel de Icaza (miguel@gnome.org)
6 //
7 // Copyright 2009 Novell (http://www.novell.com)
8 //
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:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
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.
30 // Things left to do:
31 //
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 ;-)
49 using System;
50 using System.Collections.Generic;
52 namespace System.Diagnostics.Contracts {
53 #if NET_2_1 || NET_4_0
54 public
55 #else
56 internal
57 #endif
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);
68 if (!ea.Unwind)
69 return;
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)
78 if (condition)
79 return;
80 Escalate (ContractFailureKind.Assert, null, "failure");
83 [ConditionalAttribute("DEBUG")]
84 [ConditionalAttribute("CONTRACTS_FULL")]
85 public static void Assert (bool condition, string userMessage)
87 if (condition)
88 return;
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
98 if (condition)
99 return;
101 Escalate (ContractFailureKind.Assume, null, "failure");
104 [ConditionalAttribute("CONTRACTS_FULL")]
105 [ConditionalAttribute("DEBUG")]
106 public static void Assume (bool condition, string userMessage)
108 if (condition)
109 return;
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)
152 if (predicate (t))
153 return true;
154 return false;
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++)
165 if (predicate (i))
166 return true;
168 return false;
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)
179 if (!predicate (t))
180 return false;
182 return true;
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++)
193 if (!predicate (i))
194 return false;
196 return true;
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)
226 if (!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)
236 if (!condition){
237 Escalate (ContractFailureKind.Precondition, null, userMessage);
238 throw new Exception ();
242 public static void Requires<TException> (bool condition) where TException : Exception, new ()
244 if (!condition){
245 var e = new TException ();
246 Escalate (ContractFailureKind.Precondition, e, "failure");
247 throw e;
251 public static void Requires<TException>(bool condition, string userMessage) where TException : Exception, new ()
253 if (!condition){
254 var e = new TException ();
255 Escalate (ContractFailureKind.Precondition, e, userMessage);
256 throw e;
260 public static T Result<T> ()
262 throw RewriterRequired ();
265 public static T ValueAtReturn<T> (out T value)
267 throw RewriterRequired ();