Questo è un costruttore in una delle mie classi:Perché i Contratti di codice sostengono che "Assures è falso" per questo codice?
public SemanticVersion(string version)
{
Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(version));
Contract.Ensures(MajorVersion >= 0);
Contract.Ensures(MinorVersion >= 0);
Contract.Ensures(PatchVersion >= 0);
Contract.Ensures(PrereleaseVersion != null);
Contract.Ensures(BuildVersion != null);
var match = SemanticVersionRegex.Match(version);
if (!match.Success)
{
var message = $"The version number '{version}' is not a valid semantic version number.";
throw new ArgumentException(message, nameof(version));
}
MajorVersion = int.Parse(match.Groups["major"].Value, CultureInfo.InvariantCulture);
MinorVersion = int.Parse(match.Groups["minor"].Value, CultureInfo.InvariantCulture);
PatchVersion = int.Parse(match.Groups["patch"].Value, CultureInfo.InvariantCulture);
PrereleaseVersion = match.Groups["prerelease"].Success
? new Maybe<string>(match.Groups["prerelease"].Value)
: Maybe<string>.Empty;
BuildVersion = match.Groups["build"].Success
? new Maybe<string>(match.Groups["build"].Value)
: Maybe<string>.Empty;
}
i contratti Codice bandiere checker statico un errore:
warning : CodeContracts: ensures is false: PrereleaseVersion != null
Maybe<T>
è una raccolta contenente zero o uno elementi.
Per quanto posso vedere, l'unico modo che può essere nullo è se c'è un'eccezione prima che sia assegnata, il che dovrebbe rendere irrilevanti i requisiti di Ensures. Sto andando codice cieco? Riesci a vedere il problema ...?
Aggiornamento: registrazione dell'implementazione di Forse in risposta ai commenti.
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
namespace TA.CoreTypes
{
/// <summary>
/// Represents an object that may or may not have a value (strictly, a collection of zero or one elements). Use
/// LINQ expression
/// <c>maybe.Any()</c> to determine if there is a value. Use LINQ expression
/// <c>maybe.Single()</c> to retrieve the value.
/// </summary>
/// <typeparam name="T">The type of the item in the collection.</typeparam>
public class Maybe<T> : IEnumerable<T>
{
private static readonly Maybe<T> EmptyInstance = new Maybe<T>();
private readonly IEnumerable<T> values;
/// <summary>
/// Initializes a new instance of the <see cref="Maybe{T}" /> with no value.
/// </summary>
private Maybe()
{
values = new T[0];
}
/// <summary>
/// Initializes a new instance of the <see cref="Maybe{T}" /> with a value.
/// </summary>
/// <param name="value">The value.</param>
public Maybe(T value)
{
Contract.Requires(value != null);
values = new[] {value};
}
/// <summary>
/// Gets an instance that does not contain a value.
/// </summary>
/// <value>The empty instance.</value>
public static Maybe<T> Empty
{
get
{
Contract.Ensures(Contract.Result<Maybe<T>>() != null);
return EmptyInstance;
}
}
public IEnumerator<T> GetEnumerator()
{
Contract.Ensures(Contract.Result<IEnumerator<T>>() != null);
return values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
Contract.Ensures(Contract.Result<IEnumerator>() != null);
return GetEnumerator();
}
[ContractInvariantMethod]
private void ObjectInvariant()
{
Contract.Invariant(values != null);
}
[Pure]
public override string ToString()
{
Contract.Ensures(Contract.Result<string>() != null);
if (Equals(Empty)) return "{no value}";
return this.Single().ToString();
}
}
public static class MaybeExtensions
{
public static bool None<T>(this Maybe<T> maybe)
{
if (maybe == null) return true;
if (maybe == Maybe<T>.Empty) return true;
return !maybe.Any();
}
}
}
È ovvio che 'PrereleaseVersion' viene impostato su' new Forse (...) 'o su' Forse .Empty', ed è anche ovvio che il primo non può essere 'null', quindi il mio primo l'istinto sarebbe vedere se ti manca un invariante che 'Empty' non è nullo. –
hvd
@hvd Anche il mio take. Tim ... è quell'implementazione 'Maybe' la tua o da qualche parte come [qui] (https://github.com/AndreyTsvetkov/Functional.Maybe)? –
Pubblicherò l'implementazione. Penso che il concetto sia venuto da un corso di Pluralsight ma poi ho praticamente fatto il mio. –