Upon discovering generics, I seem to be able to get 99% of a solution, but the last 1% is killing me.
Say you want to make a generic class to compare two numbers for whatever condition the user specifies...(in red)... and then return a boolean to indicate whether the first argument was related to the second argument in the chosen way
LessThan
GreaterThan
GreaterThanOrEqual
Equal
Etc...
Im sorry about the horrifyingly bad formatting of code in here, but i've tried everything in this stupid window to get the paragraph spacing to single space when hitting return, but for some reason it refuses to do so.
Anyway, since you cannot constrain a generic class to only accept Int32, Double, etc because those cannot be inherited from, and you cannot know what format the arguments are going to come to you in...
int, double
double, double
double, int
single, double
...etc, you might make a generic class that accepts 2 generic types... like so
Public Class TestGeneric(Of U, V)
and that way you can hold a variable of one type (say an Int32) and another variable of a different type, (say a Double) and do your magic comparing them in some function. Well, I wrote a class to do this and below in the function IsDataValid is where the problem arises that I cannot figure out.
Public Enum XRelatesToY
X_Equals_Y
X_IsGreaterThanOrEqual_Y
X_IsGreaterThan_Y
X_IsLessThan_Y
X_IsLessThanOrEqual_Y
End Enum
Public Class XRelatesToY(Of TypeX, TypeY) Inherits RuleBase Private _X As TypeX Private _Y As TypeY Private _XRelatesToY As XRelatesToY
Public Property X() As TypeX Get Return _X End Get Set(ByVal value As TypeX)
_X = value
End Set End PropertyPublic Property Y() As TypeY Get Return _Y End Get Set(ByVal value As TypeY)
_Y = value
End Set End PropertyPublic Property Relation() As XRelatesToY Get Return _XRelatesToY End Get Set(ByVal value As XRelatesToY)
_XRelatesToY = value
End Set End Property
Public Overrides Function IsDataValid() As Boolean
Select Case _XRelatesToY
Case XRelatesToY.X_Equals_Y
If _X <> _Y Then Return False Else Return True
Case XRelatesToY.X_IsGreaterThan_Y
Case XRelatesToY.X_IsGreaterThanOrEqual_Y
Case XRelatesToY.X_IsLessThan_Y
Case XRelatesToY.X_IsLessThanOrEqual_Y
End Select
End Function
End Class
The error message you will get here is "Operator is not defined for types _X and _Y" and even though you only intend on ever passing Int32, Double, etc which DO have those operators defined on them, this refuses to work.
So the bottom line is, how do I write a generic class that will take any two numeric types as arguments to a function, where it then compares those types for ">" or "<" or "=" etc and returns a boolean based on the type of comparison you wanted between X and Y. If you instantiate the class and choose "X_IsGreaterThan_Y" then you expect your class to accept two generic types and compare them on that basis and return a true or false.

Generics and operators...
AmyHa
Hi, I'm not sure of what you're trying to do, but comparisons only work on objects of the same type. The vb compiler hides this by handling conversions to a common type so comparisons can be done, so if you have:
if 1 < 1.0 then...
Behind the scenes, the compiler selects a common type to which both arguments can be converted (double in this case), casts both arguments to it and then compares the values. Your class would have to do something similar.
Maybe you could tell us why do you need to write such a method to compare two different types, and then we might be able to help you some more.
Ramachandran V
I am making a set of business rule classes that work against a datatable, and one of the rule classes is comparing the value of one field against another with some relationship in mind. I work for the Assessors office (property taxes). This isn't the greatest example, but for arguments sake, say for instance we have a datatable that has a column defined as a double, and another column defined as an int, and the first column holds the square footage of the first floor, while the second holds the square footage of the 2nd floor.
Well, most houses don't have more square feet on their second floor than their first unless they have a REALLY odd shaped house. So you might apply a rule that says Column1 must be greater than Column2 for any row in the datatable... well I don't want to get off on the architecture of business rules, I just want to know how to take 2 numeric values that may be any numeric type and compare them and return a boolean result indicating whether the rule was satisifed or not.
Dave Neigler
What I'd do in this case, would be in your method to cast both X and Y to double, and compare that - you may have to cast down to object first:
if cdbl(cobj(X)) < cdbl(cobj(Y)) then ...
This has the problem that you will lose some precision if both types were not double. A double cannot always represent perfectly all the digits of a decimal, for example.
Basically, if you want better results at some point some code will have to deal with the fact that you're trying to perform an operation between two different types. You can manually write the code for all combinations of types (code that determines a cast type from the types of the two arguments to the comparison, then casts each argument to that type, then performs the comparison), but unless you really need the precision, I'd go with the above solution.
The other comment is that in some cases, even increasing the precision might not return the expected results - whenever working with floating point values, remember that a particular decimal value may not have a perfect representation in a double variable - comparisons should be made against intervals around an expected value.
I think this is one of those little things that seem simple but hide some complexity - sorry :)