Skip to content
This repository has been archived by the owner on Jul 15, 2023. It is now read-only.

string.IsNullOrWhiteSpace() not considered Pure by Requires() or Invariant() when running on .NET 4.6.1 #339

Closed
Desarc opened this issue Jan 21, 2016 · 4 comments · Fixed by #426

Comments

@Desarc
Copy link

Desarc commented Jan 21, 2016

There seems to be an issue with string.IsNullOrWhiteSpace() when running Code Contracts on .NET 4.6.1. Given the following sample code:

public void StringTests()
{
     RequiresNotNullOrWhiteSpace("test");
}

public void RequiresNotNullOrWhiteSpace(string s)
{
      Contract.Requires(!string.IsNullOrWhiteSpace(s));
}

The static checker gives the following warning on the Requires() -call:

Warning CC1036  Detected call to method 'System.String.IsNullOrWhiteSpace(System.String)' 
without [Pure] in contracts of method '....TestNullOrWhiteSpace(System.String)'.

... and additionally the following warning on the RequiresNotNullOrWhiteSpace("test") -call:

CodeContracts: requires unproven: !string.IsNullOrWhiteSpace(s). Are you making some assumption 
on IsNullOrWhiteSpace that the static checker is unaware of?

I compiled exactly the same code on .NET 4.0, 4.5.1 and 4.6 without getting these warnings.

From the user documentation:

 Code Contract tools currently assume the following things are pure:
• Any method whose fully qualified name begins with System.Diagnostics.Contracts.Contract, 
System.String, System.IO.Path, or System.Type.

Additionally, the IsNullOrWhiteSpace() method is actually marked as [Pure] in .NET 4.6.1

The same problem applies to Invariant(). Given the following code, the same warnings are displayed:

private string testString = "test";

[ContractInvariantMethod]
private void TestInvariant()
{
     Contract.Invariant(!string.IsNullOrWhiteSpace(testString));
}
@yaakov-h
Copy link
Contributor

yaakov-h commented Feb 3, 2016

I suspect this is because of the conditional here combined with the fact that we fall back to .NET 3.5 contract reference assemblies if we don't have a matching condition in the targets file. #359 should fix this.

@fourpastmidnight
Copy link

I can verify that #359 does fix this issue. I modified my Microsoft.CodeContracts.targets files and the issue went away. Though, I did need to use the v4.5 assemblies when the project framework version is set to 4.6 and above. But hopefully, the PR associated with #359 takes care of all these framework version issues.

@joshjeppson
Copy link

There also seems to be an issue where CodeContracts doesn't realize that IsNullOrWhiteSpace is a stronger assertion than IsNullOrEmpty. Does #359 also fix that issue? Or just the missing [Pure] attribute?

Generates warning:

Contract.Requires(!String.IsNullOrWhiteSpace(path));
var contents = File.ReadAllText(path);

Works:

Contract.Requires(!String.IsNullOrEmpty(path));
var contents = File.ReadAllText(path);

@yaakov-h
Copy link
Contributor

I believe #359 will fix that as well, but only if your project is targeting .NET 4.6 (in VS2013) or 4.6.1 (in VS2013 or VS2015). Anything else is a separate issue.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants