Mirror of Svelto.ECS because we're a fan of it
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

447 lines
9.6KB

  1. #if DISABLE_DBC || !DEBUG || PROFILER
  2. #define DISABLE_CHECKS
  3. using System.Diagnostics;
  4. #endif
  5. using System;
  6. namespace DBC.ECS
  7. {
  8. /// <summary>
  9. /// Design By Contract Checks.
  10. ///
  11. /// Each method generates an exception or
  12. /// a trace assertion statement if the contract is broken.
  13. /// </summary>
  14. /// <remarks>
  15. /// This example shows how to call the Require method.
  16. /// Assume DBC_CHECK_PRECONDITION is defined.
  17. /// <code>
  18. /// public void Test(int x)
  19. /// {
  20. /// try
  21. /// {
  22. /// Check.Require(x > 1, "x must be > 1");
  23. /// }
  24. /// catch (System.Exception ex)
  25. /// {
  26. /// Console.WriteLine(ex.ToString());
  27. /// }
  28. /// }
  29. /// </code>
  30. /// If you wish to use trace assertion statements, intended for Debug scenarios,
  31. /// rather than exception handling then set
  32. ///
  33. /// <code>Check.UseAssertions = true</code>
  34. ///
  35. /// You can specify this in your application entry point and maybe make it
  36. /// dependent on conditional compilation flags or configuration file settings, e.g.,
  37. /// <code>
  38. /// #if DBC_USE_ASSERTIONS
  39. /// Check.UseAssertions = true;
  40. /// #endif
  41. /// </code>
  42. /// You can direct output to a Trace listener. For example, you could insert
  43. /// <code>
  44. /// Trace.Listeners.Clear();
  45. /// Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
  46. /// </code>
  47. ///
  48. /// or direct output to a file or the Event Log.
  49. ///
  50. /// (Note: For ASP.NET clients use the Listeners collection
  51. /// of the Debug, not the Trace, object and, for a Release build, only exception-handling
  52. /// is possible.)
  53. /// </remarks>
  54. ///
  55. static class Check
  56. {
  57. #region Interface
  58. /// <summary>
  59. /// Precondition check.
  60. /// </summary>
  61. #if DISABLE_DBC
  62. [Conditional("__NEVER_DEFINED__")]
  63. #endif
  64. public static void Require(bool assertion, string message)
  65. {
  66. if (UseExceptions)
  67. {
  68. if (!assertion)
  69. throw new PreconditionException(message);
  70. }
  71. else
  72. {
  73. Trace.Assert(assertion, "Precondition: " + message);
  74. }
  75. }
  76. /// <summary>
  77. /// Precondition check.
  78. /// </summary>
  79. ///
  80. #if DISABLE_DBC
  81. [Conditional("__NEVER_DEFINED__")]
  82. #endif
  83. public static void Require(bool assertion, string message, Exception inner)
  84. {
  85. if (UseExceptions)
  86. {
  87. if (!assertion)
  88. throw new PreconditionException(message, inner);
  89. }
  90. else
  91. {
  92. Trace.Assert(assertion, "Precondition: " + message);
  93. }
  94. }
  95. /// <summary>
  96. /// Precondition check.
  97. /// </summary>
  98. ///
  99. #if DISABLE_DBC
  100. [Conditional("__NEVER_DEFINED__")]
  101. #endif
  102. public static void Require(bool assertion)
  103. {
  104. if (UseExceptions)
  105. {
  106. if (!assertion)
  107. throw new PreconditionException("Precondition failed.");
  108. }
  109. else
  110. {
  111. Trace.Assert(assertion, "Precondition failed.");
  112. }
  113. }
  114. /// <summary>
  115. /// Postcondition check.
  116. /// </summary>
  117. ///
  118. #if DISABLE_DBC
  119. [Conditional("__NEVER_DEFINED__")]
  120. #endif
  121. public static void Ensure(bool assertion, string message)
  122. {
  123. if (UseExceptions)
  124. {
  125. if (!assertion)
  126. throw new PostconditionException(message);
  127. }
  128. else
  129. {
  130. Trace.Assert(assertion, "Postcondition: " + message);
  131. }
  132. }
  133. /// <summary>
  134. /// Postcondition check.
  135. /// </summary>
  136. ///
  137. #if DISABLE_DBC
  138. [Conditional("__NEVER_DEFINED__")]
  139. #endif
  140. public static void Ensure(bool assertion, string message, Exception inner)
  141. {
  142. if (UseExceptions)
  143. {
  144. if (!assertion)
  145. throw new PostconditionException(message, inner);
  146. }
  147. else
  148. {
  149. Trace.Assert(assertion, "Postcondition: " + message);
  150. }
  151. }
  152. /// <summary>
  153. /// Postcondition check.
  154. /// </summary>
  155. ///
  156. #if DISABLE_DBC
  157. [Conditional("__NEVER_DEFINED__")]
  158. #endif
  159. public static void Ensure(bool assertion)
  160. {
  161. if (UseExceptions)
  162. {
  163. if (!assertion)
  164. throw new PostconditionException("Postcondition failed.");
  165. }
  166. else
  167. {
  168. Trace.Assert(assertion, "Postcondition failed.");
  169. }
  170. }
  171. /// <summary>
  172. /// Invariant check.
  173. /// </summary>
  174. ///
  175. #if DISABLE_DBC
  176. [Conditional("__NEVER_DEFINED__")]
  177. #endif
  178. public static void Invariant(bool assertion, string message)
  179. {
  180. if (UseExceptions)
  181. {
  182. if (!assertion)
  183. throw new InvariantException(message);
  184. }
  185. else
  186. {
  187. Trace.Assert(assertion, "Invariant: " + message);
  188. }
  189. }
  190. /// <summary>
  191. /// Invariant check.
  192. /// </summary>
  193. ///
  194. #if DISABLE_DBC
  195. [Conditional("__NEVER_DEFINED__")]
  196. #endif
  197. public static void Invariant(bool assertion, string message, Exception inner)
  198. {
  199. if (UseExceptions)
  200. {
  201. if (!assertion)
  202. throw new InvariantException(message, inner);
  203. }
  204. else
  205. {
  206. Trace.Assert(assertion, "Invariant: " + message);
  207. }
  208. }
  209. /// <summary>
  210. /// Invariant check.
  211. /// </summary>
  212. ///
  213. #if DISABLE_DBC
  214. [Conditional("__NEVER_DEFINED__")]
  215. #endif
  216. public static void Invariant(bool assertion)
  217. {
  218. if (UseExceptions)
  219. {
  220. if (!assertion)
  221. throw new InvariantException("Invariant failed.");
  222. }
  223. else
  224. {
  225. Trace.Assert(assertion, "Invariant failed.");
  226. }
  227. }
  228. /// <summary>
  229. /// Assertion check.
  230. /// </summary>
  231. #if DISABLE_DBC
  232. [Conditional("__NEVER_DEFINED__")]
  233. #endif
  234. public static void Assert(bool assertion, string message)
  235. {
  236. if (UseExceptions)
  237. {
  238. if (!assertion)
  239. throw new AssertionException(message);
  240. }
  241. else
  242. {
  243. Trace.Assert(assertion, "Assertion: " + message);
  244. }
  245. }
  246. /// <summary>
  247. /// Assertion check.
  248. /// </summary>
  249. ///
  250. #if DISABLE_DBC
  251. [Conditional("__NEVER_DEFINED__")]
  252. #endif
  253. public static void Assert(bool assertion, string message, Exception inner)
  254. {
  255. if (UseExceptions)
  256. {
  257. if (!assertion)
  258. throw new AssertionException(message, inner);
  259. }
  260. else
  261. {
  262. Trace.Assert(assertion, "Assertion: " + message);
  263. }
  264. }
  265. /// <summary>
  266. /// Assertion check.
  267. /// </summary>
  268. ///
  269. #if DISABLE_DBC
  270. [Conditional("__NEVER_DEFINED__")]
  271. #endif
  272. public static void Assert(bool assertion)
  273. {
  274. if (UseExceptions)
  275. {
  276. if (!assertion)
  277. throw new AssertionException("Assertion failed.");
  278. }
  279. else
  280. {
  281. Trace.Assert(assertion, "Assertion failed.");
  282. }
  283. }
  284. /// <summary>
  285. /// Set this if you wish to use Trace Assert statements
  286. /// instead of exception handling.
  287. /// (The Check class uses exception handling by default.)
  288. /// </summary>
  289. public static bool UseAssertions
  290. {
  291. get
  292. {
  293. return useAssertions;
  294. }
  295. set
  296. {
  297. useAssertions = value;
  298. }
  299. }
  300. #endregion // Interface
  301. #region Implementation
  302. // No creation
  303. /// <summary>
  304. /// Is exception handling being used?
  305. /// </summary>
  306. private static bool UseExceptions
  307. {
  308. get
  309. {
  310. return !useAssertions;
  311. }
  312. }
  313. // Are trace assertion statements being used?
  314. // Default is to use exception handling.
  315. private static bool useAssertions = false;
  316. #endregion // Implementation
  317. } // End Check
  318. class Trace
  319. {
  320. internal static void Assert(bool assertion, string v)
  321. {
  322. #if NETFX_CORE
  323. System.Diagnostics.Contracts.Contract.Assert(assertion, v);
  324. #else
  325. System.Diagnostics.Trace.Assert(assertion, v);
  326. #endif
  327. }
  328. }
  329. #region Exceptions
  330. /// <summary>
  331. /// Exception raised when a contract is broken.
  332. /// Catch this exception type if you wish to differentiate between
  333. /// any DesignByContract exception and other runtime exceptions.
  334. ///
  335. /// </summary>
  336. public class DesignByContractException : Exception
  337. {
  338. protected DesignByContractException() {}
  339. protected DesignByContractException(string message) : base(message) {}
  340. protected DesignByContractException(string message, Exception inner) : base(message, inner) {}
  341. }
  342. /// <summary>
  343. /// Exception raised when a precondition fails.
  344. /// </summary>
  345. public class PreconditionException : DesignByContractException
  346. {
  347. /// <summary>
  348. /// Precondition Exception.
  349. /// </summary>
  350. public PreconditionException() {}
  351. /// <summary>
  352. /// Precondition Exception.
  353. /// </summary>
  354. public PreconditionException(string message) : base(message) {}
  355. /// <summary>
  356. /// Precondition Exception.
  357. /// </summary>
  358. public PreconditionException(string message, Exception inner) : base(message, inner) {}
  359. }
  360. /// <summary>
  361. /// Exception raised when a postcondition fails.
  362. /// </summary>
  363. public class PostconditionException : DesignByContractException
  364. {
  365. /// <summary>
  366. /// Postcondition Exception.
  367. /// </summary>
  368. public PostconditionException() {}
  369. /// <summary>
  370. /// Postcondition Exception.
  371. /// </summary>
  372. public PostconditionException(string message) : base(message) {}
  373. /// <summary>
  374. /// Postcondition Exception.
  375. /// </summary>
  376. public PostconditionException(string message, Exception inner) : base(message, inner) {}
  377. }
  378. /// <summary>
  379. /// Exception raised when an invariant fails.
  380. /// </summary>
  381. public class InvariantException : DesignByContractException
  382. {
  383. /// <summary>
  384. /// Invariant Exception.
  385. /// </summary>
  386. public InvariantException() {}
  387. /// <summary>
  388. /// Invariant Exception.
  389. /// </summary>
  390. public InvariantException(string message) : base(message) {}
  391. /// <summary>
  392. /// Invariant Exception.
  393. /// </summary>
  394. public InvariantException(string message, Exception inner) : base(message, inner) {}
  395. }
  396. /// <summary>
  397. /// Exception raised when an assertion fails.
  398. /// </summary>
  399. public class AssertionException : DesignByContractException
  400. {
  401. /// <summary>
  402. /// Assertion Exception.
  403. /// </summary>
  404. public AssertionException() {}
  405. /// <summary>
  406. /// Assertion Exception.
  407. /// </summary>
  408. public AssertionException(string message) : base(message) {}
  409. /// <summary>
  410. /// Assertion Exception.
  411. /// </summary>
  412. public AssertionException(string message, Exception inner) : base(message, inner) {}
  413. }
  414. #endregion // Exception classes
  415. } // End Design By Contract