How Can I Compare Any Numeric Type To Zero In C#
I would like to create a function that checks if a numeric value passed as an argument has a value greater than zero. Something like this:
public bool IsGreaterThanZero(object value)
{
if(value is int)
{
return ((int)value > 0);
}
else if(value is float)
{
// Similar code for float
}
return false;
}
Can I try to cast the object passed as the function's argument to one numeric data type so I can then compare it to zero rather than checking for each type in my if statement? If the cast fails I would return false. Is there a better(read shorter, more readable) way to do this?
Edit: Some have asked about if I know the type will be a numeric, why the object etc. I hope this makes things clearer.
This function would be part of a Silverlight converter that implements the IValueConverter
interface which has a convert signature of
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
A first, I only wanted the converter to work with ints but my imagination started to r开发者_开发知识库un wild and think what if I have floating point numbers and other numeric types. I wanted to make the converter as flexible as possible. Initially I thought all this extra information would get in the way of what I wanted to do so I didn't include it in my question.
My preference would be:
public bool IsGreaterThanZero(object value)
{
if(value is IConvertible)
{
return Convert.ToDouble(value) > 0.0;
}
return false;
}
This will handle all IConvertible types safely (which includes all floating point and integer types in the framework, but also any custom types).
Does the caller know the type? If so, how about:
public static bool GreaterThanZero<T>(T value) where T : struct, IComparable<T>
{
return value.CompareTo(default(T)) > 0;
}
No conversions needed, and should work for any of the built-in numeric types - and any sensible value types you come up with yourself. (For example, this would be fine with Noda Time's Duration
struct.)
Note that the caller doesn't have to know the type directly - it may only know it as another type parameter with the same constraints. Admittedly this may not be appropriate for your situation, but I thought I'd mention it anyway. If nothing knows the type at compile-time (and you don't fancy getting dynamic typing to do the job for you in C# 4!) then calling Convert.ToDouble
is probably your best bet - just be aware that it may have problems for System.Numerics.BigInteger
from .NET 4.0.
Eh? What numeric types do you care about?
public bool IsGreaterThanZero(double value)
{
return value > 0;
}
These all work ...
IsGreaterThanZero((int)2);
IsGreaterThanZero((long)2);
IsGreaterThanZero((double)2);
IsGreaterThanZero((float)2);
IsGreaterThanZero((byte)2);
IsGreaterThanZero((ulong)2);
You can avoid boxing and unboxing using generics:
Here's the definition of a function
class GenericComparation {
public static bool IsGreaterThanZero<T>(T value) where T : IComparable<T> {
// Console.WriteLine(value.GetType().Name)
return value.CompareTo(default(T)) > 0;
}
}
Usage:
Console.WriteLine(GenericComparation.IsGreaterThanZero(1));
Console.WriteLine(GenericComparation.IsGreaterThanZero(-1.1));
Console.WriteLine(GenericComparation.IsGreaterThanZero(Decimal.Zero));
Try:
double tempValue;
if(double.TryParse(value.ToString(), out tempValue)
{
return (tempValue > 0)
}
else
{
return false;
}
Why not just Convert.ToDouble or Convert.ToDecimal and then do the comparison? Seems like that would handle most types that someone might pass in.
This simplest and fastest way to compare any numeric type To zero is as follows:
public bool IsGreaterThanZero(object value)
{
if (value != null && value.GetType().IsValueType)
return System.Convert.ToDouble(value) > 0;
return false;
}
精彩评论