Note: I have removed the full listing of the tdecimal
class from the main page of the blog simply because it is so long. You can download the source code from here: tdecimal.cs
In this post I will look at key sections of the class, from the top down, and note some of the features or reasons for some of the code.
/// Roster of possible formats to be used to display tdecimal values. public enum ValueFmt { undefined, currency, nbr, pct }
The ValueFmt enumeration is used by the display code (which I will present in a later post). You can see it being used in the previous post to display values as currency amounts.
#if DEBUG
The use of the DEBUG preprocessor flag is very important to tdecimal
for two reasons:
In its current implementation, tdecimal
finds the source code file and line number by walking up the internal stack trace and looking for the first file that is not its own source file. This will not work when the application is compiled since the source files are not available to the internal stack trace. To avoid this, the tdecimal
class does not try to obtain filename information when it is not in DEBUG mode.
tdecimal
does a lot of extra processing. I saw no need to slow down the released application by having it collect a lot of tracing information that would rarely (if ever) be used.
/// /// Catalogue of the value types that are to be returned by operations on tdecimal objects /// (e.g. if a currency is divided by a currency, the result should be a percentage). /// private static Dictionary<string, ValueFmt> resultType = new Dictionary<string, ValueFmt>
Because tdecimal
was created for use in a business application, the only operations that it needed to handle were the basic +, -, / and *.
string filename = String.Empty; do { StackFrame callingStack = (new StackTrace(true)).GetFrame(frameLevel++); filename = Path.GetFileName(callingStack.GetFileName()); _assignedAt = filename + " [" + callingStack.GetFileLineNumber() + "]" + " : " + callingStack.GetMethod().Name; } while (filename == tdecimal.tdecimalCodeFile);
This is the section of code that walks up the stack and gets the source code filename of the calling method. This will be far easier to implement in .NET 4.5’s Caller Attributes (http://blogs.msdn.com/b/vijaysk/archive/2012/09/27/net-4-5-information-of-caller-function-caller-attributes-in-net-4-5.aspx). I’m looking forward to this because it means that I can, if I wish, include tdecimal
functionality in a production environment.
#region Static Properties (common) /// Gets a tdecimal value equal to 0. public static tdecimal Zero { get { return new tdecimal(0); } } #endregion static properties (common)
I ran into a problem when trying to use a literal number where a tdecimal
was expected, such as
return tdecimal.Named(this.IsBonusable ? _totalBonusable : 0, "Total Bonusable");
0 won’t work here since the compiler will complain that the conditional expression cannot be resolved because tdecimal
and int convert to one another (since Named() can accept either a tdecimal
or an int, the compiler can’t decide whether to change _totalBonusable to an int or change 0 to a tdecimal
).
To get around this, I created the constant Zero. Fortunately, I didn’t need to create One, Two, Three, etc.
return tdecimal.Named(this.IsBonusable ? _totalBonusable : tdecimal.Zero, "Total Bonusable"); #region Implicit Conversions (common)
Again, I was writing for a business application, so I only needed to convert between some basic numeric types.
I think that covers of the more important code sections within this class. In a later post, I will look at how to display the tdecimal
trace tree.