public static class PositiveInt32Extensions
{
public static Boolean IsPositive( this Int32 candidate, out PositiveInt32 value ) => PositiveInt32.TryCreate( candidate, out value );
}
public readonly struct PositiveInt32
{
public static Boolean TryCreate( Int32 candidate, out PositiveInt32 value )
{
if( candidate > 0 )
{
value = new PositiveInt32( candidate );
return true;
}
else
{
value = default;
return false;
}
}
private readonly Int32 value;
public PositiveInt32( Int32 value )
{
if( value < 1 ) throw new ArgumentOutOfRangeException( nameof(value), actualValue: value, message: "Value must be positive." );
this.value = value;
}
public static implicit operator Int32( PositiveInt32 self ) => self.value;
// NOTE: This implicit conversion will fail when `unsignedValue > UInt32.MaxValue / 2`, but I assume that will never happen.
public static implicit operator PositiveInt32 ( UInt32 unsignedValue ) => new PositiveInt32( (Int32)unsignedValue );
}