Comparing Anonymous Objects in C# and VB

Trust me: There's actually a tip at the end of this column, but it's going to take me awhile to get there. Be patient -- I do have a point and I am getting to it.

When it comes to comparing objects, what .NET considers the same isn't what normal human beings consider the same. Consider this code that creates two Customer objects, both representing Customer A123:

Dim cust1 As New Customer("A123")
Dim cust2 as Customer
cust2 = cust1

In VB, if I try to compare the two objects using this syntax, I get a compile time error:

If cust1 = cust2 Then

I can, however, use this syntax and the result, unsurprisingly, is True:

If cust1.Equals(cust2) Then

The test is true, however, only because the variable cust1 is pointing at the same object as the variable cust2. The .NET documentation refers to this as "reference equality." If, however, I create two separate objects, as this code does, and compare cust1 and cust2, the test returns false:

Dim cust1 As New Customer("A123")
Dim cust2 As New Customer("A123")
If cust1.Equals(cust2) Then

The test fails because the cust1 variable is pointing at a different object than cust2, even though the two objects, presumably, represent exactly the same customer entity and have identical values in all of their properties.

We, as human beings, might consider these objects to be "the same" because the objects represent the same data -- that's called "value equality" -- but we're not .NET. C# gives the same results as VB, but is willing to accept the x == y syntax.

Anonymous and Different
.NET uses object equality for most objects, but there are exceptions. For scalar variables and strings, for instance, .NET uses value equality. As a result, this test is true:

Dim num1 As Integer = 2
Dim num2 As Integer = 2
If num1 = num2 Then

Things are also different if you use anonymous objects -- but only if you're using C#. In C#, you might create two anonymous objects like this:

var x = new {  id = "A123", 
    CompanyName = "PH&V Information Services" };
var y = new {  id = "A123", 
    CompanyName = "PH&V Information Services" };

In C#, this test is false:

if (x == y)

But this test is true:

if (x.Equals(y))

For anonymous objects and with the Equals method, C# stops using reference equality and starts using value equality: C# compares the value of properties with identical signatures (names and types). But wait! It gets worse. In VB, the anonymous objects look like this:

Dim x = New With {.id = "A123", 
    .CompanyName = "PH&V Information Services"}
Dim y = New With {.id = "A123", 
    .CompanyName = "PH&V Information Services"}

The x = y syntax is still an error but this test, which looks just like the C# test, gives the same answer as with "un-anonymous objects" and remains false:

If x.Equals(y) Then

So, unlike C#, VB continues to use reference equality with anonymous objects.

Listen: It's not my fault.

The Tip (Finally)
This is, of course, an accident waiting to happen. The good news is that you can fix this difference in behavior (and, by "fix", I mean: get the almost identical behavior almost everywhere). As a bonus, it simplifies your VB code when you do want to compare two anonymous objects: Just use the Key keyword to identify to VB properties to be used when comparing anonymous objects. Using Key causes VB to switch to using value equality when comparing anonymous objects, just like C#.

This example flags just the id property in my anonymous object as providing the value to be used when comparing this anonymous object with another anonymous object:

Dim x = New With {Key .id = "A123", CompanyName …
Dim y = New With {Key .id = "A123", CompanyName …

The x = y syntax is still a syntax error, but x.Equals(y) now returns the same result as the equivalent C# test: True. And, actually, VB's approach is more flexible than C#'s, as you can choose what counts as equality: all of the properties on the object or some arbitrary collection. One caveat: If you're comparing anonymous objects in either C# or VB, they must have identical sets of properties or the comparison automatically fails.

Of course, in C# x == y still returns a different result than x.Equals(y) for anonymous objects.

Hey: There's only so much I can do.

Posted by Peter Vogel on 06/25/2012 at 1:16 PM8 comments


Creating Inheritance Relationships in Entity Framework

Far too many developers are under the impression that the business entities that Entity Framework (EF) creates in database-first mode are the business entities you're stuck with: one entity = one table. That's not true; and when you need a more sophisticated design, you can create that.

For instance, imagine a Customers table that contains several different kinds of customers (e.g. "premium" and "ordinary" customers") -- usually flagged by some kind of ‘CustomerType' column. You could create a single class with methods filled with "If…then" statements that check the CustomerType property and run the right code.

Or you could create two classes: a PremiumCustomer entity class with all and only the code/properties that relate to premium customers and a TypicalCustomer entity class with all and only the code/properties that relate to a TypicalCustomer. The code and properties that are common to both sets of customers would stay in a base Customer entity that the other two classes inherit from.

The beauty of EF is that it would manage all the updates made through the three entities back into the single table. If you tell EF about the CustomerType column, it will ensure that the right object is created when retrieving rows in the table, and update the column correctly when you create a new entity.

To implement this design, first let the EF wizard generate your its default entities from your tables. Then right-mouse click on the EF designer and select Add | Entity.  In the resulting dialog, give your new entity a name (e.g., "PremiumCustomer") and specify that it inherits from an existing class (e.g., "Customer") using the Base type dropdown list. You can then cut and paste properties from one class to another (e.g. does the "DiscountRate" only apply to PremiumCustomers? Then select that property in the Customer class, cut it, and paste it into the PremiumCustomer's properties). 

You won't be instantiating the original, base class entity in code anymore, so select it, and in its Properties Window, set its Abstract property to True (i.e. from now on I'll use PremiumCustomer or TypicalCustomer, but not Customer, so I make the Customer entity abstract).

Now you need to tell EF about your type column so it will know when to create the right object. Right-mouse click on one of your new classes (e.g., PremiumCustomer) and select Table Mapping to display the mappings between table columns (on the left) and entity properties (on the right); right now the mapping table will be empty. Click on <Add Table or View> and select your table (e.g., Customers) to tie the table your new entity. Click on the new <Add a Condition> choice and select your type column. In the Value/Property column, enter the data that identifies the row (if it's a string value, make sure you put quotes around the value). Repeat for your other new entities. Finally, delete your type column from your base table -- EF will take of making sure it's set correctly.

And you're done! You now have several classes managing a single table, but the right class will be generated for you at the right time by EF (and, when it adds new rows to your table, it will make sure that your type column is updated correctly). You also have less logic to design because you just have to put the code appropriate for each entity in each of your entities.

Posted by Peter Vogel on 06/21/2012 at 1:16 PM0 comments


The Incredibly Useful Sysinternals Suite

If you like knowing what's going on with your computer -- even if it doesn't have much to do with .NET development -- you'll like the Sysinternals kit from Microsoft. The Sysinternals kit bundles up almost 70 utilities that extract information from Windows. And, while not aimed specifically at .NET developers, it's surprising (to me) how often I've found some of these tools useful when building business applications.

For instance, if you place BigInfo in your StartUp folder, it adds a bitmap to your desktop with your computer's TCP/IP address, OS version, service pack, and last time the computer was rebooted (among other information). I include BigInfo as a matter of course on all my development VMs and test machines.

One of my clients found that, after installing a Windows Service I built for them, that the service gradually took over the whole computer. We used RamMap to track how memory was being allocated by Windows and discovered that, while my service was taking over the whole computer, it was because the computer had nothing else to do. Given another application to run, Windows gave that other application the memory it needed.

If you've ever wondered exactly what DLLs a running process is using -- or what processes are using a particular DLL -- ListDlls will tell you. I was trying to replace a DLL on a computer that some process owned and it was ListDLL that identified the process. I then used another utility in the suite, PsKill, to end that process (PsKill also has the power to kill processes on other computers -- a power I've never used but have really, really wanted to, on occasion).

I will admit that I've never used MoveFile or AutoRuns for development purposes. But MoveFile will tell you what files are going to be updated after your next reboot (for instance, after an installation program tells you have to reboot), so you can make a semi-informed decision about putting off the reboot.

AutoRuns gives you a complete list of what programs are set up to run when your computer starts up, including items from the Startup Folder and programs being executed through the various Run* registry keys. I'm only interested in third party tools when I use AutoRuns, so I use the –m option to hide the Microsoft applications.

I used Strings (which lists all the Unicode and ASCII strings embedded in EXEs or DLLs in a folder, or its subfolders) against a third-party DLL once. Strings let me track down all the config files the application was using -- something not obvious from the documentation.

There's lots more goodies in the suite, but if you want to run one of them without going to the trouble of downloading it, you can use Systinternals Live. In Windows Explorer (or a command prompt), just enter \\live.sysinternals.com\tools\ followed by the name of the tool you want.

Posted by Peter Vogel on 06/14/2012 at 1:16 PM0 comments


4 Must-Know Visual Studio Keyboard Shortcuts

Here are four keyboard short cuts for things you probably do often in Visual Studio.

  1. You want to add a blank line after the line you're on. You don't have to go to the end of the line and hit the <Enter> key. Just leave your cursor where it is and use Ctrl+Shift+Enter (Ctrl+Enter adds a line above).

  2. You want to uncomment a block of commented code. You don't have to select the whole commented block. Just put your cursor somewhere in the commented block and type the uncomment chord: Ctrl+K, U.

  3. You've got an error on line and see the little red bar that marks the SmartTag that provides the options for fixing the problem. You don't have to fiddle with the mouse to display the dropdown list of options. You can just type Ctrl+. (You don't even have to move your cursor back to the line in error).

  4. You type an object name, type a period, type the first letter of the member you want and get an IntelliSense list with lots and lots of entries. You don't have to type the whole name of the member you want. IntelliSense in Visual Studio 2010 recognizes camel-casing, so if you hold down the Shift key and type the capitalized letters in the member name you want, IntelliSense will give narrow the list down to that one.

Posted by Peter Vogel on 05/31/2012 at 1:16 PM18 comments


Guru Tip: How to Activate a SharePoint Ribbon Tab in Sandboxed Solutions

I went back to Andrei Smolin, a team leader at Add-In Express, for some more SharePoint help. I wanted to activate a Ribbon Tab using, I thought, code like this:

SPRibbon  currentRibbon = SPRibbon.GetCurrent(this.Page);
currentRibbon.MakeTabAvailable("<Tab  Id>");
currentRibbon.InitialTabId  = "<Tab Id>";

Unfortunately, I wanted to use this code in a Sandboxed solution -- something that's specifically forbidden. Andrie pointed out that my code wouldn't work very well in a farm solution, either: the tab would get selected but it wouldn't get activated.

Andrie gave me the following script, which not only bypasses the Sandbox limitation but actually activates the tab. This code works with a feature called SPRibbon and a tab with the ID AdxspRibbonTab1, so you'll need to change those two names in your code:

var ribbonReady = false;

function onBodyLoaded() {
  if (!ribbonReady) {
    if ((typeof (_ribbonReadyForInit) == 'function') &&
         _ribbonReadyForInit()) {
      ribbonReady = true;
      var control = get_SPRibbon().FindControl("AdxspRibbonTab1");
      if (control != null) {
        var tabElem = document.getElementById(control.getFullId() +
                                              "-title");
        if (tabElem && tabElem.firstChild) {
                    tabElem.firstChild.click();	
        }
      }
    }
  }
};

if (_spBodyOnLoadFunctionNames != 'undefined' && 
    _spBodyOnLoadFunctionNames != null) {
    _spBodyOnLoadFunctionNames.push("onBodyLoaded");
}
onBodyLoaded();

Posted by Peter Vogel on 05/17/2012 at 1:16 PM0 comments


Dealing with Local Databases, or Why Your Updates Don't Stick

Probably everyone in the world but me knows how Visual Studio handles database files during testing in a GUI-based project. Since I work primarily in ASP.NET projects, I didn't clue into this behavior until recently. But even if you do know about this "feature," you may not be aware of how you can improve on Visual Studio's default behavior.

Here's what happens: You add a database to some non-ASP.NET project to use for testing. You run some code that makes some updates and everything seems to work with all of your updates accepted. You then do a second run…and it's like your previous run never happened! And sure enough, when you go to Server Explorer and browse to the rows that should have been changed in the first run you can see that the data is unchanged.

That's because, when you press F5, Visual Studio quietly copies your database from your project's root folder to the bin/Debug folder, and that's the version of the database that your code updates. When you think about it, this is a good idea: Individual test runs leave your test data unchanged. But if you want one test run to build on the changes from a previous test run…well, you're out of luck.

To check the results of your test runs, you'll need to add a connection in Server Explorer to the version of the database in your bin/Debug folder. Just turn on Show All Files at the top of Solution Explorer, drill down through the bin and Debug folders, and double-click on the database file to add it to Server Explorer. While that will let you check the results of any test run in Server Explorer, you still won't be able to have one test run build on the changes made by a previous test run.

To get that to happen, you'll need to change the Copy to Output Directory property on the database file in your project's root. The default setting for the property is "Copy Always." The setting you probably want is "Copy If Newer". This will copy the database from the project root only if you make some change to the database and build your project. Now, if you make some changes in a test run, those changes will still be there in your next test run.

When you want to restore to your original test data, just delete the database file in the Debug folder from Solution Explorer and build your project (if you want to see the database file after it's been copied to the folder, you'll need to click the Refresh button at the top of Solution Explorer).

And my thanks to my buddy Greg Adams, who explained it to me (he didn't have to draw me pictures, but it was a near thing).

Posted by Peter Vogel on 05/14/2012 at 1:16 PM1 comments


Seeing Your Code Even When IntelliSense Hides It

Sometimes when I'm typing in parameters I get both an IntelliSense drop down list of helpful suggestions and the tip on what this parameter should be. I'm not denying that's tremendously helpful, but sometimes these hints completely cover up my actual code -- and I need to see my code!

If you've been using the Escape key to dismiss these text blocks to get back to your code, there's a better solution (especially if you, in fact, want those tips back later to figure out what to do): Just press the Ctrl key. With the Ctrl key pressed, all the "helpfulness" blocks become transparent, letting you see your code. Release the Ctrl key and the "helpfulness" comes back.

Posted by Peter Vogel on 04/30/2012 at 1:16 PM1 comments


Guru Tip: Sending an Email in Office 365

What I don't know about SharePoint and Office 365 is what keeps companies like Add-In Express in business. So, when, I couldn't figure out how to send an email in Office 365, I asked Andrei Smolin, a team leader at Add-In Express.

In Office 365, there's no direct way to send an email programmatically because the SPUtility.SendEmail Method isn't available in sandboxed solutions. The workaround is to use the Send an Email action in a list workflow. First, you need to create a custom list:

  1. In the Navigation pane, click Lists and Libraries
  2. On the Lists and Libraries tab, click Custom List in the New group. In the resulting dialog, enter a name and description for the list
  3. Click OK

The list should contain at least three text columns: one to store each of the email's address, subject and body. Then, create a list workflow bound to the list:

  1. Click on the File menu and select Add Item
  2. Under the Workflows tab, select List Workflow
  3. Enter a name for your workflow and select your list from the dropdown list

Add a step to the workflow that performs theSend an Email action. When setting up this action, define the email message so that it looks up the values from the columns of the current item. You can also consider adding a second step to the workflow to delete the item just processed.

At this point, you have a list and a workflow tied to it. Now, adding an item to the list will cause your workflow to send an email. You may choose to just let your user trigger sending an email by adding items to that list through the SharePoint user interface. However, you can also add an item to the list from code to trigger sending an email. Assuming your list is called SendMail and has columns called Subject, To, and Message, that's what this code fragment shows:

using Microsoft.SharePoint; 
... 
SPWeb mySite = SPContext.Current.Web; 
SPListItemCollection  listItems = mySite.Lists["SendMail"].Items; 
SPListItem item =  listItems.Add(); 
item["Subject"] =  "subject"; 
item["To"] =  "user@server.com"; 
item["Message"] =  "message"; 
item.Update(); 

Posted by Peter Vogel on 04/12/2012 at 1:16 PM1 comments


Accessing a Dictionary Using Multiple Keys

Dictionaries and some other collection objects allow you to store an item along with a key value. This allows you to retrieve the item later, either by position or by key value. This code stores a value under the key "PHVIS," and finishes by setting the variable Result to "Peter Vogel":

Dim Items As New Dictionary(Of String,  String)
Items.Add("PHVIS", "Peter  Vogel")
Dim Result As String
Result = Items("PHVIS")  

But what if you want to store something by two values -- storing sales amounts by CustomerName and SaleDate, for instance? You could just concatenate two values together to create a single key, but a better solution would be to define a class to hold the two values to use as the key. Unfortunately, using a class won't work. When testing for equality, these collections will use an object's hashcode, returned from the class' GetHashCode method, to determine if two objects are identical. Two different objects, even if they're from the same class and have identical values in their properties, are considered to be different under this test.

But if you use a Structure instead,, everything works. Structures are scalar types rather than reference types like objects, so their values are compared to determine equality. A structure to hold two values might look like this:

Structure TwoValue
  Public CustomerId As String
  Public SaleDate As DateTime
End Structure

To use this structure, you might store a customer's sales under the customer's identifier, and the date that the sale was made:

Dim Items As New Dictionary(Of TwoValue, Integer)
Dim Key As TwoValue
Key.CustomerId = "A123"
Key.SaleDate =  Date.Parse("11/01/2010")
Items.Add(Key, 132)

Retrieving the value just consists of assembling a matching key and passing the key to the Dictionary. This example will retrieve the value and puts it in the variable Result: 

Dim Result As Integer
Dim Key2 As TwoValue
Key2.CustomerId = "A123"
Key2.SaleDate =  Date.Parse("11/01/2010")

Result = items(Key2)

Posted by Peter Vogel on 04/04/2012 at 1:16 PM5 comments


Stop Scanning Solution Explorer for Your Files

If you scroll up and down through Solution Explorer looking for files in long list -- stop! Did you know that Solution Explorer acts like a searching list? For instance, if you type the same letter over and over again, Solution Explorer will scroll through all the folders and files with names that begin with that letter. So instead of hitting the same letter again and again, you type different letters, Solution Explorer assumes that you're typing the file name and will scroll to the file with that name.

Solution Explorer will even leap over project boundaries and burrow into Solution folders to find the file whose name you're typing. The only downside is that Solution Explorer only searches the items you can see in Solution Explorer; it won't expand collapsed files, folders, projects, or Solution folders.

Posted by Peter Vogel on 04/01/2012 at 1:16 PM2 comments


Free Tool: Replace NotePad with NotePad2

Like last month's free tool, this month's tool isn't really a .NET-specific tool. However, I can't program without NotePad (though it was a long time ago when I did the XML schemas for a major software developer's products and my primary tools were NotePad and Internet Explorer). At the very least I often find myself using NotePad whenever I want to look at some code from Windows Explorer and don't want to start up Visual Studio.

I've used a couple of NotePad replacements (TextPad for the longest time) but my current favorite is NotePad2 by Florian Balmer. I like that it's fast to start up and load a file while still doing everything Notepad does. But I also like that it does code highlighting, will generate autoclose tags for XML and HTML, has a recent files list, and will minimize to the tray (so it's ready for all the other things that I use it for). A tool like NotePad2 is always going to be a trade-off: I'm looking for a speedy tool but I also want lots of functionality. NotePad2 hits the sweet spot for me.

If you try it and like it, you can have NotePad2 replace NotePad with a tweak to the Windows registry. You can even have NotePad2 support Windows 7's jump list of recently accessed files with a few more tweaks (and did I mention that NotePad2 has a Favorites list where you can add files you return to repeatedly?). Scott Hanselman's blog at has links to descriptions of how to get NotePad2 to replace NotePad (including how to get NotePad2 to support Window 7's jump list of recently accessed files).

Posted by Peter Vogel on 03/28/2012 at 1:16 PM3 comments


Guru Tip: Avoid the HTML5 FOUJUI Experience

As I continue to incorporate more JavaScript into my applications and, especially, as I try to leverage the new JavaScript/HTML 5 technologies, I'm discovering a new problem: It's now possible for users to see raw, uninitialized HTML in their browser before my JavaScript properly arranges things. I asked Todd Anglin, VP for HTML5 Web & Mobile Tools at Telerik, if there was a solution to this problem. Here's what he said:

This is a new problem that can ruin the fancy, new experience of your HTML5 app. I think of it as FOUJI, or Flash of Uninitialized JavaScript UI: Users see the ugly HTML briefly and then, suddenly, the page looks right. One solution for this problem is to use a JavaScript loading screen that "hides" the page HTML as it initializes.

For instance, this HTML displays some gif (probably animated) that lets users know that their page is being prepared:

<div id="preLoad">
  <div>
    <img src="styles/BlueOpal/loading-image.gif"  alt="Loading Image"
 style="width:48px;" />
    <br />Loading...
  </div>
</div>
I use it with this CSS:
#preLoad{            
    width:100%;
    height:100%;
    background:#FFF;
    position:absolute;
    top:0;    
}        
 
#preLoad div{
    position:absolute;
    top: 50%;
    left: 50%;
    height:60px;
    margin-top: -30px;
    margin-left: -24px;
}

To make the loading screen "go away" when I've finished setting it up, I trigger a new event when the JavaScript that initializes my page is complete:

$(document).trigger("APP_READY");
In my main page, I wire up code to that event to hide my loading screen:
$(document).bind("APP_READY",function(){ 
    $("#preLoad").fadeOut(); 
});

Now users see the loading screen until my app finishes initializing. Then the loading screen fades out to reveal the UI -- without FOUJUI.

The richness of HTML5 Web apps is great, but it includes extra challenges like FOUJUI as you make the transition to the client. One of the things that we're doing with the Kendo UI is provide another solution: server-side helpers that render the HTML on the server before sending it to the user. In the meantime, you have to check your apps for any unintended flashing.

Todd had more to say on improving this solution (including incorporating CSS3 Transitions) on his blog.

Posted by Peter Vogel on 03/25/2012 at 1:16 PM11 comments


Upcoming Events

.NET Insight

Sign up for our newsletter.

I agree to this site's Privacy Policy.