问题
I'm attempting to use Contracts in my .Net 3.5 (C#) project. I found where I had written something like if (string.IsNullOrEmpty(s) || string.IsNullOrEmpty(s.Trim())) throw new ArgumentException("Required", "s");
at the beginning of methods.
I could keep them there and use legacy contracts. I could change it to Contract.Requires(s!= null && string.IsNullOrEmpty(s.Trim()));
. But besides not being very sure about the correctness or performance of the Whitespace part of the condition, those are lame (opinion).
Instead, I tried to encapsulate the condition in a method for use in Contracts. Problem is that I still can't figure out how to describe the Whitespace part declaratively. The static checker finds several issues depending on how I write it.
I'd like to hear comments about the appropriateness of data content checks such as this one for whitespace AS WELL AS a correct definition.
public static class str
{
[Pure]
public static bool IsNullOrWhitespace(string s)
{
Contract.Ensures(s != null || Contract.Result<bool>());
Contract.Ensures((s != null && !Contract.ForAll<char>(s, c => char.IsWhiteSpace(c))) || Contract.Result<bool>());
if (s == null) return true;
for (var i = 0; i < s.Length; i++)
{
if (!char.IsWhiteSpace(s, i))
{
Contract.Assume(!Contract.ForAll<char>(s, c => char.IsWhiteSpace(c)));
return false;
}
}
return true;
}
}
This might be sloppy, but my initial experimentation method is here. The Asserts on a, b, and c are failing or are unproven.
static void Test()
{
string a = null;
string b = "";
string c = " ";
string d = "xyz";
string e = " xyz ";
if (!str.IsNullOrWhitespace(a))
{
Contract.Assert(a != null);
a = a.Trim();
}
if (!str.IsNullOrWhitespace(b))
{
Contract.Assert(b != null && b != "");
b = b.Trim();
}
if (!str.IsNullOrWhitespace(c))
{
Contract.Assert(c != null && c != " ");
c = c.Trim();
}
if (!str.IsNullOrWhitespace(d))
{
d = d.Trim();
}
if (!str.IsNullOrWhitespace(e))
{
e = e.Trim();
}
}
回答1:
Here's the built-in contract from .NET 4:
Contract.Ensures(
(Contract.Result<bool>() && ((str == null) || (str.Length == 0)))
? ((bool) true)
: ((Contract.Result<bool>() || (str == null))
? ((bool) false)
: ((bool) (str.Length > 0)))
, null, "Contract.Result<bool>() && (str == null || str.Length == 0) ||\r\n!Contract.Result<bool>() && str != null && str.Length > 0");
Despite its complexity, you can see that there is no mention of whitespace. I've tried several times, but I can't get something working that will satisfy the static checker.
There appear to be a couple of issues stopping me from writing it, so I've filed some questions on the Code Contracts forum.
My contract was:
Contract.Ensures(Contract.Result<bool>() ==
(s == null || Contract.Exists(s, char.IsWhiteSpace)))
来源:https://stackoverflow.com/questions/4865173/net-3-5-implementation-of-string-isnullorwhitespace-with-code-contracts