tdecimal: class listing and discussion


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.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s