Smart value classes

Smart value classes

Old forum URL: forums.lhotka.net/forums/t/1006.aspx


ajj3085 posted on Thursday, August 24, 2006

Hi,

I'm building some Smart classes, much like the SmartDate class.  One thing I'd like to do is add implicit conversions.  Decimal to SmartDecimal is pretty straight foreword.  However, I'd like some opinions on how to go the other way. 

My choice is to either not provide an implicit SmartDecimal to decimal.  The other is to return Value, even if the SmartDecimal is currently 'empty.'

Anyone have thoughts on this?

Thanks
Andy

SonOfPirate replied on Thursday, August 24, 2006

We are in the process of implementing the same type of thing.  In all of our ValueTypes we explicitly implement System.IConvertible to handle indirect conversion rather than try to incorporate all the different variations implicitly.  As you said, Decimal to SmartDecimal is straight-forward and expected behavior, but Decimal to Single, etc. we leave to the IConvertible interface (which allows us to simply delegate to the internal Decimal, in this case, which already exposes IConvertible).

Hope that helps.

 

ajj3085 replied on Thursday, August 24, 2006

Pirate,

Yes, I've implemented IConvertable as well.  I had no plans to do implict conversions for anything but going between SmartDecimal and decimal.

So it sounds as if leaving out an implicit SmartDecimal to decimal is your recommendation.

Thanks
Andy

SonOfPirate replied on Thursday, August 24, 2006

Sorry, had to go back and look at what we've done...

Yea, I've always left it so that the decimal value had to be "promoted" to the new type (SmartDecimal) and not the other way around.  But, we do expose a Value property that returns the base type (decimal).

The only exception to this is when overloading operators.  In that case we implement both - actually all 3:

public static SmartDecimal operator+(SmartDecimal a, SmartDecimal b)
public static SmartDecimal operator+(SmartDecimal a, Decimal b)
public static SmartDecimal operator+(Decimal a, SmartDecimal b)

When implementing, the last two create a new SmartDecimal from the Decimal and delegate to the first for the actual work.

And, I believe that it was because of the operator overloads that we do not implement implicit conversion in both directions.  If we did, if memory serves me correctly, depending on the order of the arguments, adding a SmartDecimal to a Decimal would cause it to convert the SmartDecimal to a Decimal and then do straight Decimal addition.  That may not seem like a big deal in this case, but we have other value types, such as Rational, that we want to control the operator methods so it is important the the 'primitive' types be converted 'up' to our type.  I could be remembering wrong, though, it's been a while since this was done.

 

xal replied on Thursday, August 24, 2006

Allow me to chime in with a question: What do you do when you have an empty value and try to compare against that?
That is an important factor because it affects rules and sorting. Are you implementing something like rocky did with smartdate and EmptyIsMin ?


Andrés

ajj3085 replied on Thursday, August 24, 2006

I do something similar to what Rocky did, yes.

SonOfPirate replied on Thursday, August 24, 2006

Likewise.  When converting from our type to a 'primitive' type, we have a property that allows us to indicate what value to use.  For instance, our SmartBoolean will (by default) return false when converted to Boolean if the SmartBoolean's value is null but this can be toggled to true if for some reason we want that to be our default.

ajj3085 replied on Thursday, August 24, 2006

Even with that knowledge though, I'm thinking implicit SmartBool -> bool shouldn't be allowed... you're assuming the developer will know what the MinIsEmpty value is and that they'll get that value should the variable be empty... seems too dangerous to me.

While we're talking about this; do you strickly stick to Rocky's implementation where MaxValue really is empty if that's what's stored?  I did something a little different, and keep a seperate flag.  This allows the object to store both empty and and Max and Min.  Obviously you had to do that for the boolean.. but did you take the effort to the numerics as well?

Andy

SonOfPirate replied on Thursday, August 24, 2006

I took a cue from Nullables and use the internal flag.  I didn't care for the fact that Rocky's implementation eliminated use of a legitimate value for the variable.  However, to allow the Value property to return something, we had to provide a way to set what that value was going to be.  So, in that regard, we did do it Rocky's way.  BUT, this is only in the Value property if the internal 'empty' flag is set.

What I am considering now is to carry the Nullable concept a little farther and instead of having the Value property return this 'dummy' value, completely eliminate it and have it throw an exception if accessed when the object is 'empty'.  I have to see what this does to my data access code before implementing, though, to make sure I don't break things elsewhere.

 

ajj3085 replied on Thursday, August 24, 2006

I agree; although extereme values, it did eliminate 2 values from a finite set.. never sat completely well with me either.

Of course if MS had had proper support for Nullable types and databinding, this would likely be a moot issue.  Maybe in .Net 3.0..

Andy

SonOfPirate replied on Thursday, August 24, 2006

We can only hope.

Copyright (c) Marimer LLC