Synopsis: I have a need to take two generic C# objects, and if they are numerical, compare them using either less than or greater than comparisons.
Problem: I can't figure out how to have my class implement IComparable as described in this post: Having to implement a generic less than and greater than operation. If that's not even the proper path to take, then I need to know that as well.
Background: I have implemented the RequiredIf ValidationAttribute found at A more complex custom validator but needed the > and < options in addition to an equals comparison.
Code (taken from A more complex custom validator, one-third down the page):
private bool IsRequired(object actualPropertyValue)
{
switch (Comparison)
{
case Comparison.IsLessThan:
case Comparison.IsLessThanOrEqualTo:
case Comparison.IsGreaterThan:
case Comparison.IsGreaterThanOrEqualTo:
if (!Value.IsNumber())
{
throw new Exception("The selected comparison option is only applicable to numeric values");
}
break;
}
switch (Comparison)
{
case Comparison.IsNotEqualTo:
return actualPropertyValue == null || !actualPropertyValue.Equals(Value);
case Comparison.IsEqualTo:
return actualPropertyValue != null && actualPropertyValue.Equals(Value);
case Comparison.IsGreaterThan:
// THIS LINE FAILS BECAUSE actualPropertyValue DOESN'T IMPLEMENT IComparable
return actualPropertyValue != null && (actualPropertyValue.CompareTo(Value) > 0);
// The rest of the comparison cases go here...
default:
throw new Exception("Comparison value is not defined");
}
}
Static Helper Extensions:
public static bool IsNumber(this object value)
{
if (value is sbyte) return true;
if (value is byte) return true;
if (value is short) return true;
if (value is ushort) return true;
if (value is int) return true;
if (value is uint) return true;
if (value is long) return true;
if (value is ulong) return true;
if (value is float) return true;
if (value is double) return true;
if (value is decimal) return true;
return false;
}
It sounds like you should just be able to cast actualPropertyValue
to IComparable
:
IComparable comparable = (IComparable) actualPropertyValue;
return comparable != null && comparable.CompareTo(Value) > 0;
Note that your use of the word "generic" is curious here. If you actually made it generic, you could write:
private bool IsRequired<T>(T actualPropertyValue) where T : IComparable
Then you wouldn't need the cast.
int MyCompare (object a, object b)
{
var ac = a as IComparable;
var bc = b as IComparable;
if (ac == null || bc == null)
throw new NotSupportedException();
return ac.CompareTo(bc);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With