This week's tip comes from Bobby Orndorff of GrapeCity software. He's the Chief Architect for Spread.NET, and implemented the Spread Calculation Engine and the Chart component.
Floating point numbers have limited precision. This can lead to small approximation errors in calculations which, in turn, can cause unexpected results when comparing calculation results. For example, consider the following C# code, which multiples a number by its multiplicative inverse and then compares the calculated result with the expected result of one.
double x = 49.0;
double y = 1 / x;
double calculatedResult = x * y;
double expectedResult = 1.0;
bool areSame = calculatedResult == expectedResult;
We would expect areSame to be true, because the product of a number and its multiplicative inverse should always equal one. However, areSame will be false in the above code. The problem is that 1/49 cannot be represented exactly using the double data type. This introduces a small approximation error in y which in turn introduces a small approximation error in calculatedResult. This example demonstrates why it's unwise to perform an "exactly equals" comparison of floating point numbers.
To allow for small approximation errors in calculations, it's better to perform an "almost equals" comparison of floating point numbers which checks whether the numbers are close to each other. This involves checking whether the difference between the numbers is less than some epsilon.
The problem then becomes choosing an epsilon. Any fixed epsilon would likely be too small when comparing large numbers, or too large when comparing small numbers. Thus, it's desirable to choose a relative epsilon that is relative in magnitude to the numbers being compared. Note that the double data type uses 64 bits, with 1 bit for sign, 11 bits for exponent, and 52 bits for mantissa. If we choose epsilon by dividing one of the numbers by 2^n, a difference of less than epsilon will indicate that the numbers being compared agree about the first n bits of the mantissa. For example, consider an AlmostEqual method that compares the difference of the two numbers to the first number divided by 2^48.
public static bool AlmostEqual(double a, double b)
{
if (a == b)
{
return true;
}
return Math.Abs(a - b) < Math.Abs(a) / 281474976710656.0;
}
This method will return true when the two numbers match to about the first 48 bits of the mantissa (i.e., only disagree in about the last 4 bits of the mantissa). Note that the method has code to handle the special case when the two numbers are exactly equal. We can then rewrite our original code example using the AlmostEqual method in place of the == operator.
bool areSame = AlmostEqual(calculatedResult, expectedResult);
Now areSame will be true, indicating that caluclatedResult is close enough to expectedResult that any difference could easily be an approximation error due to limitations of the double data type.
Note that the above AlmostEqual method is not perfect. Zero will only compare almost equal to zero. Thus, the above AlmostEqual method doesn't account for approximation errors when one of the numbers being compared is zero.
Posted by Peter Vogel on 11/08/20115 comments
Sometimes you really, really, really want to see the SQL that LINQ generates when working with the Entity Framework. For instance, in a comment to a
recent tip
, a reader mentioned that a LINQ to Entities query generated a SQL statement that joined more than 40 tables. The application's performance was, to say the least, disappointing. If you're not getting what you expect from your LINQ queries, being able to see the SQL statement can give you real clues in tracking down the problem, as it did with that column's reader.
More
Posted by Peter Vogel on 11/03/20114 comments
In a recent
article
on using LINQ with Entity Framework, I recommended using Entity Framework's navigation properties in your LINQ statements instead of joins. The code is easier to write and the SQL generated for you will automatically include the necessary joins.
However, the following won't generate an SQL statement that joins the Orders table to the Employees table because the LINQ query doesn't reference the Employees objects:
Dim res = From o In nw.Orders
Where o.Freight > 0
Select o
For Each ord In res
EmpName = ord.Employee.FirstName
'…code using the employee name
Next
In this case, the navigation properties aren't being used until the For…Each loop that follows the LINQ statement. The compiler isn't smart enough to spot that, so the SQL statement that's generated from the LINQ query won't include a join to the Employee table. Instead, Employee rows will probably be fetched one by one from the database as the code loops through the collection of Order objects retrieved through the LINQ query. This would be terrifically inefficient if, as this code does, every Order is going to have its related Employee object processed.
The solution is to give LINQ some advice about what you intend to do. In the same way that ADO.NET will process requests faster if you tell it more (for instance, if you know that only a single row will be retrieved, using ADO.NET's SingleResult option will give you better performance), LINQ will work faster for you if you tell it what you need. In this case, using the Include keyword tells LINQ that it should add a join to the SQL statement to fetch the related Employee rows:
Dim res = From o In nw.Orders.Include("Employees")
Where o.Freight > 0
Select o
As a developer, you'll have to make some decisions here. If, for instance, the loop in the previous example had an If statement that ensured that only some of the Employee records were going to be processed, it might make sense to omit the Include keyword. With the Include keyword gone, only the Employee rows that were actually needed in the loop would be fetched. You may need to run some tests to see if using Include makes your application run faster or slower. Fortunately, as with SQL, switching between the two versions of the LINQ statement is easy to do (delete or add the Includes), so it's relatively easy to do some time trials and see what gives you the best performance.
Posted on 10/26/20115 comments
The ASP.NET DataViews, when connected to a DataSource, generate all the buttons a user needs to edit, update and delete the data that the DataView displays (assuming that you enable edits, updates and deletes).
But what if you want to add some additional functionality to the form? If, for instance, you want the user to be able to click a button to run a credit check on the currently displayed customer? Or, for some change that requires coordinating changes to several values, you want to give the user the ability to implement the update with a single button click? Or, by clicking a button, delete not the currently displayed record but some other, related set of records (i.e. "Delete all orders for this customer")? You can put that code where it belongs -- associated with the DataView -- rather than scattered through several Click events by using the FormView's ItemCommand method.
All you have to do is drop a Button of your own onto the form and set the Button's CommandName property to some string. When the user clicks on any Button on the DataView, the DataView fires its ItemCommand event. The e parameter to that event has a property called CommandName that's automatically set to whatever was in the CommandName property of the button that triggered the event. You can use that value to check to see which Button was clicked and execute your code. Typical ItemCommand code will look like this:
Select Case e.CommandArgument
Case "CreditCheck"
'....
Case "DeleteAllOrders"
'....
'CommandArguments for other buttons
End Select
This event has two other properties useful in this scenario. The CommandArgument property contains the value of the CommandArgument property on the Button the user clicked. You can store data in the CommandArgument that will be passed to the ItemCommand event when the Button is clicked. Less useful is the CommandSource, which points at the Button that fired the event (the sender parameter passed to the event points to the DataView).
And, because the ItemCommand event fires for every Button on the page and fires before any of the events triggered by that button, the ItemCommand event lets you preview all other Button clicks on the page. This allows you to use the ItemCommand event as a central point-of-control for every Button on the DataView.
Posted by Peter Vogel on 10/24/20112 comments
In my recent
review
of Document! X 2011, a tool for generating MSDN-style documentation for your projects by scanning your assemblies, a reader pointed out that you can achieve many of the same results by using Ghost Doc and Sandcastle. I've discussed
Ghost Doc
More
Posted by Peter Vogel on 10/19/20110 comments
Through the WebClient and AssemblyPart.Load method, Silverlight lets you download DLLs dynamically at runtime from the server to the client. This lets you defer dragging the DLL to the client until you know you need it.
To use the DLL you'll download at runtime, you still need to add a reference to the DLL in order to get IntelliSense support at design time (and also to get your application to compile). But because you're going to download the class through code at runtime, you don't need to include that DLL in your project. So, after adding a reference to the DLL, you can set its Copy Local to False.
Using the DLL in your Silverlight application is a little awkward. While you instantiate the class with the New keyword, as usual, you must do it in a dedicated method decorated with MethodImpl attribute, passing the NoInlining parameter. Something like this, for instance:
<System.Runtime.CompilerServices.MethodImpl(
System.Runtime.CompilerServices.MethodImplOptions.NoInlining)>
Private Function CreateMyObject() As Object
Return New MyDynamicClass
End Function
But you can't actually use the resulting object in that method. Instead, to make Silverlight's type checking happy, you need to defer using that class to a completely separate method:
Private Sub UseMyObject(dc As Object)
Dim dc As MyDynamicClass = CType(dc, MyDynamicClass)
mou.SomeMethod()
End Sub
Attempting to instantiate and use the class in the same method will just generate some bewildering error messages.
Posted by Peter Vogel on 09/28/20112 comments
Retrieving data from the GridView can involve passing integer values to the GridView's Rows and Cells properties—resulting in code that's not only hard to read but brittle: it will break as soon as you add, remove, or reorder the columns in the GridView. But there's an easy way to pull out data if you use the GridView's SelectedValue property. You've probably used the SelectedValue property with a listing control (e.g. the DropDownList, the RadioButtonList).
More
Posted by Peter Vogel on 09/09/20111 comments
Generally speaking, developers hate nulls. While an integral part of relational database theory (where they represent an unknown value), eventually nulls get passed to some variable that won’t accept them and your code blows up. Coalesce operators allow you to check for nulls and return a default value when one is found—and do it in a single line of code. In Visual Basic, the coalesce operator is If(), in C#, it’s ??.
More
Posted by Peter Vogel on 09/08/20113 comments
When you have a method that could do more than one thing, you have two ways to implement the method: Enclose the different processes in If…Then or Select…Case statements, or implement the strategy pattern. With the strategy pattern, you pass to the method not just data but also the processing. As a result, the method’s code loses all those ugly logic statements, making it easier to test and maintain. One way to pass processing to a method—and, probably, the simplest—is to pass a lambda expression.
More
Posted by Peter Vogel on 09/06/20110 comments
YouTrack is JetBrains' Web-based issue-tracking system. The latest version supports customizable workflows (using the free workflow editor) and better support for mobile devices, among other goodies. For developers who hate taking their hands off the keyboard, YouTrack supports both a command language and a search language that allow you to bypass the UI and just do what you want. YouTrack doesn't integrate with Visual Studio, but you can submit issues from e-mail (and also get notifications through Jabber, the open source instant messaging standard).
More
Posted by Peter Vogel on 09/06/20110 comments
Sometimes there is some processing that needs to be added to every page on the site. For instance, I had a client who wanted to add code to every WebForm's PreInit event to set Page's Theme property dynamically. Changing every PreInit event in every page sounded like the definition of no fun at all.
But there's a better solution. One place to put code required on every page is in an HttpModule. HttpModules process every page request that comes into the site. You can create your own HttpModule so that, when a request for a page comes to the site, you can add to code to any event on the page.
More
Posted by Peter Vogel on 08/12/20110 comments
When I have lots of documents open in Visual Studio, I find it difficult to scan the tabs to find the document I want (I recognize that this may not be a problem for everyone). I often find myself double-clicking on files in Solution Explorer to pop it to the front of the tabs, even though I know the file is already open -- somewhere.
Or, I used to. Lately, I've added a new key stroke combination to my limited repertoire: Ctrl_Alt_Down Arrow causes the list of open files in the upper right corner of the editor window to pop open all by itself. That list is searchable, which means that if you start typing your file name, the focus shifts to the first file with a name that matches what you've typed so far. Since I (usually) know my file's name, I can press Ctrl_Alt_Down, type as much of my file name as necessary to highlight it in the list, and hit the enter key to open the file in a tab.
More
Posted by Peter Vogel on 08/11/20117 comments