Your argument validation could be de-duplicated.
Here, take a look:
MinMaxI
if (_bits < 2 || _bits > 64)
{
throw new System.ArgumentOutOfRangeException("_bits", _bits,
String.Format("2 <= _bits <= 64"));
}
MinI
if (_bits < 2 || _bits > 64)
{
throw new System.ArgumentOutOfRangeException("_bits", _bits,
String.Format("2 <= _bits <= 64"));
}
MaxI
if (_bits < 2 || _bits > 64)
{
throw new System.ArgumentOutOfRangeException("_bits", _bits,
String.Format("2 <= _bits <= 64"));
}
MaxN
if (_bits < 1 || _bits > 64)
{
throw new System.ArgumentOutOfRangeException("_bits", _bits,
String.Format("1 <= _bits <= 64"));
}
They're practically the same!
I'd make a method like this (I'm not really familiar with C# syntax, so let me know if I made a mistake)
private static void validateBitsArgument(ulong _bits, ulong min, ulong max){
if (_bits < min || _bits > max)
{
throw new System.ArgumentOutOfRangeException("_bits", _bits,
String.Format("{0} <= _bits <= {1}", min, max));
}
}
And then include it like this:
public class Bits
{
public static void MinMaxI(ulong _bits, out long _min, out long _max)
{
validateBitsArgument(_bits, 2, 64);
_min = ~(long)0 << (int)(_bits - 1);
_max = -1 - _min;
}
public static long MinI(ulong _bits)
{
validateBitsArgument(_bits, 2, 64);
return ~(long)0 << (int)(_bits - 1);
}
public static long MaxI(ulong _bits)
{
validateBitsArgument(_bits, 2, 64);
return -1 - (~(long)0 << (int)(_bits - 1));
}
public static ulong MaxN(ulong _bits)
{
validateBitsArgument(_bits, 1, 64);
return _bits == 64 ? ~(ulong)0 : ~(~(ulong)0 << (int)_bits);
}
private static void validateBitsArgument(ulong _bits, ulong min, ulong max){
if (_bits < min || _bits > max)
{
throw new System.ArgumentOutOfRangeException("_bits", _bits,
String.Format("{0} <= _bits <= {1}", min, max));
}
}
}
And voila, shorter code.