Readonly Code Contracts and Crash in Private Static Fields

I have a private readonly static field in my class:

public class MyClass { // ISSUE #1 -- requires unproven: path != null private static readonly DirectoryInfo MyDirectory = new DirectoryInfo(Settings.Default.MyDirectoryPath); protected virtual void SomeMethod() { if (MyDirectory.Exists) { // ISSUE #2 -- requires unproven: !string.IsNullOrEmpty(path) var catalog = new DirectoryCatalog(MyDirectory.FullName); } } } 

For problem # 1, I used the default null coalescing operator for some magic string and fixed it, but I don't really like this solution. I was hoping there was a better solution.

For question No. 2, I can only think about what I use Contract.Assumes because if I try to use Contract.Requires(MyDirectory.Exists || !String.IsNullOrEmpty(MyDirectory.FullName)); , he complains about visibility (private field used in the request of the protected method).

+4
source share
4 answers

Problem # 1 is the result of Settings.Default.MyDirectoryPath , which is code created by Visual Studio without any property contracts. This problem is not limited to null strings. Many APIs now have contracts that require TimeSpan be non-negative, but using a parameter directly associated with the API, a code contract warning will be generated.

The way to solve this problem is to wrap the parameter in a method that has a contract. For instance:.

 String GetMyDirectoryPath() { Contract.Ensures(Contract.Result<String>() != null); var myDirectoryPath = Settings.Default.MyDirectoryPath; Contract.Assume(myDirectoryPath != null); return myDirectoryPath; } 

Note that Contract.Assume really does validate your parameter (which cannot be verified by code contracts, as it is controlled by an external configuration file). If there was a TimeSpan , which is expected to be non-negative, you can use Contract.Assume to perform a check leading to a ContractException or other method, using your own exception instead.

Adding this extra layer is somewhat tedious, but since the parameter is defined outside the application, it must be checked at runtime at some point, just like you need to check the user's interactive input.

Problem number 2 is probably because DirectoryInfo does not have any contracts. The easiest way to use Contract.Assume . This will make an expression about what you think DirectoryInfo expected behavior is, but the runtime check will still be in place to make sure your belief is correct (assuming you keep the checks in your code).

 var path = MyDirectory.FullName; Contract.Assume(!string.IsNullOrEmpty(path)); var catalog = new DirectoryCatalog(path); 
+1
source

After using Code Contracts in the current project, for some time I found that it forces you to sometimes rewrite your code in order to correct errors. You really have two options.

  • You can add settings to your project settings in order to deduce which correct attributes to apply - this ignores certain warnings. This is done by adding the "-outputwarnmasks" flag to the "Advanced static checking options" in the "Advanced" section of the "Code Contracts" tab of the project file parameters. This will add information to the Build Output window, which will indicate the correct attributes to ignore individual cases. (very useful when working with Entity Framework).
  • You can rewrite your code to add relevant requirements and provide a code so that warnings do not appear.

If you want to rewrite the code: To solve problem # 1, you have to wrap the "Settings" class and set the new MyDirectoryPath as a property that is not generated by the code, so you can add it and return an empty string and add Contract.Ensures(Contract.Result<string>() != null) at the top of the Getter for the property.

To solve problem # 2, you will need to wrap you with access to the class field inside a private static property that will add the correct requirements and requirements.

I used to rewrite code wherever possible, except with Entity Framework / LINQ, where you need to add attributes, especially with complex queries.

** Disclaimer ** This is exactly how I found to solve problems, since there is not much information about other ways to work with these types of elements.

+1
source

Well, for problem number 2, I think you can use && not || . But besides this, perhaps for problem # 1, can you put these checks into a static constructor? Another option for problem # 2 is for the method to take the directory as a parameter:

 private static readonly DirectoryInfo MyDirectory; static MyClass() { Contract.Requires(Settings.Default.MyDirectoryPath != null); MyDirectory = new DirectoryInfo(Settings.Default.MyDirectoryPath); } protected void SomeMethod() { SomeOtherMethod(MyDirectory); } protected virtual void SomeOtherMethod(DirectoryInfo directory) { Contract.Requires(directory.Exists && !String.IsNullOrEmpty(directory.FullName)); var catalog = new DirectoryCatalog(directory.FullName); } 

I don’t have much experience with the API Contract , so I could disconnect from my rocker with all this. :)

0
source

Contract.Requires (MyDirectory.Exists ||! String.IsNullOrEmpty (MyDirectory.FullName));

Do not do that! MyDirectory.Exists can change at any time, and the caller cannot guarantee this. Just throw an exception if the directory does not exist - this requires exceptions.

0
source

All Articles