Designs | Resume | KamranAyub.com | email: ayubx003 (@umn.edu)

« Oh My God, Browsing the World in 3D [Google Earth] | Main | WEB 1001 and WEB 1002, Introduction to Web Design [Webinars] »

Using the Power of LINQ to Easily Manage Collections of Objects [Awesome] | Posted at 4:15 PM

I am currently working a WPF BlackJack implementation to further develop my object-oriented and .NET skills. I have a great book called VB 2008 Recipes. It’s all sorts of useful and I recently came across a super great way to manage my annoying collections of cards, players, etc. in the game.

Instead of implementing interfaces like IList or IEnumerator for, say, a Hand of cards, you can create a variable/property called Cards with a type List(Of Card). This creates a generic list of objects of type Card (your card class, or any other type of class you want a collection of).

Then, as in my case, you can perform some powerful functions that would otherwise take more lines of code to do. For example, in BlackJack an Ace can be valued as either 1 or 11, depending on whether or not it will make the Hand total over 21 (a bust).

The way I calculate the total value for a hand, I calculate the total of all non-ace cards and then calculate the total of the Aces based on that other total.

Here was the original code I used before implementing LINQ:

Dim Cards() As Card
Dim hasAces as Boolean = False
' Calculate total for non-Ace cards
For Each myCard As Card In Cards
    Select Case myCard.Rank
        Case Card.RankType.Ace
            ' Aces
            hasAces = True
        Case Else
            intTotal += myCard.Value
    End Select
Next

If hasAces Then
    ' Do the same thing as above, only select case Ace
    ' and figure out the total
End If

That is a simplified version. Now, witness the power of LINQ combining that Select statement into a single line!

Imports System.LINQ.Enumerable

[...]

Dim Cards As List(Of Card)

' Calculate total for non-Ace cards
' PS. I <3 LINQ
intTotal = Cards.Where(Function(c) c.Rank <> Card.RankType.Ace).Sum(Function(c) c.Value)

' Any Aces?
If Cards.Any(Function(c) c.Rank = Card.RankType.Ace) Then

End If

As you can see, WAY more manageable! The reason LINQ can do this is because the System.Linq.Enumerable namespace has Extension methods like Sum, Where, Average, Max, Min, etc. that work with any kind of collection.

Previously, I was aware of LINQ to SQL and how great that was, but I didn't realize LINQ also worked with Objects (hence, LINQ to Objects).

Like I said earlier, instead of making my Hand class implement an IList, etc. I can just make Cards a property so that when I need to add a card, retrieve a card, etc from an external class, all I need to do is:

MyHand.Cards.Add(new Card)

or

MyHand.Cards(0)

If you want more information about LINQ to Objects, check it out on MSDN!

Filed Under: Coding How To Tips and Tricks

Post a comment