Entries in C# (12)

Silverlight 2.0 Video Tutorials

Silverlight 2.0 provides a new and exciting framework for building rich applications using C#, VB.NET or other languages that are capable of running on multiple operating systems and in multiple browsers.  Scott Guthrie recently posted a great set of tutorials on Silverlight 2.0 that are an excellent resource for getting started building Silverlight 2.0 applications. 

Scott recently approved converting the tutorials into video so I've been busy the past few days putting together video tutorials that cover Silverlight 2.0 and the Digg.com application Scott wrote about.  Links to the written tutorials and video tutorials are shown below.

Silverlight 2.0 Video Tutorials

Part 1: Creating "Hello World" with Silverlight 2 and VS 2008TutorialVideo Tutorial
Part 2: Using Layout ManagementTutorialVideo Tutorial
Part 3: Using Networking to Retrieve Data and Populate a DataGridTutorialVideo Tutorial
Part 4: Using Style Elements to Better Encapsulate Look and FeelTutorialVideo Tutorial
Part 5: Using the ListBox and DataBinding to Display List DataTutorialVideo Tutorial
Part 6: Using User Controls to Implement Master/Details ScenariosTutorialVideo Tutorial
Part 7: Using Templates to Customize Control Look and FeelTutorialVideo Tutorial
Part 8: Creating a Digg Desktop Version of our Application using WPFTutorialVideo Tutorial


View other cool videos on Silverlight 2.0 and additional .NET technologies from the Mix 08 conference:

Joshua Allen's Mix 08 Blog


del.icio.us Tags: ,,,,
Posted on Saturday, March 8, 2008 at 10:12PM by Registered CommenterDan Wahlin in , , , , , , , | CommentsPost a Comment | EmailEmail | PrintPrint

Building an N-Layer ASP.NET Application with LINQ, Lambdas and Stored Procedures (Updated)

Update:  I refactored some of the code and also did a better job ensuring Dispose() is called everywhere so that the DataContext object gets cleaned up properly.

Download the Application Here

.NET 3.5 has a lot of great new features that can significantly enhance developer productivity.  I've been spending some time lately working on a little sample application that demonstrates how an N-Layer ASP.NET 3.5 application can be built using LINQ, lambdas and LINQ with stored procedures.  The application is for a talk I'll be giving at DevConnections in April discussing how LINQ technologies can be used in an N-Layer architecture.  In a previous post comparing different LINQ options I mentioned that I'd be posting the code download as soon as it was ready.

The application provides a presentation layer, business layer, data layer and model layer through separate projects as shown next:

image

It also demonstrates how the new ListView control can be used to display data, perform insert, update and delete operations and nest other controls such as the GridView.  Databinding on the presentation layer is mainly done using the ObjectDataSource control.

Application Example

All of the queries performed in the application go against an object model created using the Visual Studio 2008 LINQ to SQL Designer. 

Note:  The included Northwind SQL Express database has been modified slightly to add a TimeStamp field into the Customer and Orders tables.  Doing so simplifies updates so be aware that if you change the connection string to point to a standard Northwind database you'll get an error since the TimeStamp fields will be missing.


3 Options for Data Access

Rather than focusing solely on LINQ, I wanted to show different options for data access that .NET 3.5 offers so that developers can get a feel for what's available in addition to standard LINQ queries that seem to get most of the attention these days.  I ended up creating six main data layer classes as shown next:

Customer Query Classes:

  • CustomerDBLINQ - Executes customer related queries using inline LINQ
  • CustomerDBLambda - Executes customer related queries using lambda expressions
  • CustomerDBSprocs - Executes customer related queries using stored procedures and LINQ

Order Query Classes:

  • OrderDBLINQ - Executes order related queries using inline LINQ
  • OrderDBLambda - Executes order related queries using lambda expressions
  • OrderDBSprocs - Executes order related queries using stored procedures and LINQ

I still lean toward using stored procedures due to the security and maintenance benefits they offer in more enterprise environments, but for small queries I actually prefer lambda expressions over LINQ (not sure why...just feels more object oriented I guess).  If you currently use stored procedures in your applications and haven't checked out the new LINQ to SQL Designer you'll be impressed with how easy it is to call stored procedures and pass parameters.  You never have to see or create another SqlCommand or SqlParameter object again (well...in many cases anyway).


Switching Between Data Access Classes

By changing a value in web.config you can switch between the different data layer classes and see which option you prefer (LINQ, lambdas or LINQ with sprocs).  All of the data access classes perform the same overall tasks, they just use different techniques to do it.

<appSettings>
  <!-- 
    Used to define which DB layer class should be loaded and used. 
    Valid customer values include:  Data.CustomerDBSprocs, Data.CustomerLINQ, Data.CustomerLambda
    Valid order values include: Data.OrderDBSprocs, Data.OrderLINQ, Data.OrderLambda
  -->
  <add key="CustomerDBType" value="Data.CustomerDBLINQ" />
  <add key="OrderDBType" value="Data.OrderDBLINQ" />
  <!-- When the following key is set to "true" ensure that 
EnablePartialRendering is set to false on the Default.aspx ScriptManager control --> <add key="EnableDataContextLogging" value="false" /> </appSettings>

Over the next few weeks I'm hoping to make some time to walk through the application pieces.  I may create some video tutorials about it as well....we'll see how time goes.

 

Posted on Monday, February 18, 2008 at 06:27PM by Registered CommenterDan Wahlin in , , , , | CommentsPost a Comment | EmailEmail | PrintPrint

LINQ and Lambdas and Sprocs....Oh My!

There's a lot of great stuff in .NET 3.5 and several different ways to work with LINQ technologies such as LINQ to SQL.  I'm currently putting together some demonstration code for a talk I'll be giving at DevConnections in Orlando and showing how LINQ, Lambdas and LINQ with stored procedures can be used to do the same thing so that people get a feel for each technique.  For shorter queries I generally prefer lambdas since it's more object-oriented feeling compared to LINQ (to me anyway).  For more complex queries LINQ is much easier though.  Overall, I still prefer stored procedures since you have much more control over security that way and can maintain queries without resorting to C#/VB.NET code changes in some cases.  Plus, LINQ makes it really easy to pass parameters to stored procedures without having to create SqlParameter objects (something I've always despised).

Although I've found that I like lambdas a lot for more simple queries, I was working on some lambda code yesterday that was just plain out of control and much more complex when compared to using LINQ or LINQ against a sproc.  Here's an example of the overall query I was after which has several inner joins.  This particular query was automatically generated using LINQ code and I logged the output and converted it to a stored procedure named ap_GetOrderDetailsByOrderID.  It's structured a little differently than I would typically write, but accomplishes the same end goal.

CREATE PROCEDURE dbo.ap_GetOrderDetailsByOrderID
    (
        @OrderID int
    )
AS
    BEGIN
        SELECT [t5].[CompanyName] AS [ShipperName], 
        [t5].[ProductName] AS [Product], 
        [t5].[value] AS [Total], 
        CONVERT(Int,[t5].[Quantity]) AS [Quantity], 
        [t5].[UnitPrice], 
        [t5].[CompanyName2] AS [SupplierName] 
        FROM ( 
            SELECT [t0].[OrderID], 
                    [t1].[CompanyName], 
                    [t2].[UnitPrice], 
                    [t2].[Quantity], 
                    [t3].[ProductName], 
                    [t4].[CompanyName] AS [CompanyName2], 
                    (CONVERT(Decimal(29,4),[t2].[Quantity])) * [t2].[UnitPrice] AS [value] 
            FROM [dbo].[Orders] AS [t0] 
            INNER JOIN [dbo].[Shippers] AS [t1] ON [t0].[ShipVia] = ([t1].[ShipperID]) 
            INNER JOIN [dbo].[Order Details] AS [t2] ON [t0].[OrderID] = [t2].[OrderID] 
            INNER JOIN [dbo].[Products] AS [t3] ON [t2].[ProductID] = [t3].[ProductID] 
            INNER JOIN [dbo].[Suppliers] AS [t4] ON [t3].[SupplierID] = ([t4].[SupplierID]) ) 
        AS [t5] WHERE [t5].[OrderID] = @OrderID 

    END

The examples that follow go against the LINQ to SQL objects shown next that I created in Visual Studio 2008 using the LINQ to SQL Designer.  All of the objects came from the Northwind database except the custom OrderDescription object.

image

Using LINQ

LINQ can be used to automatically generate the query shown above by doing the following:

public override IEnumerable<OrderDescription> GetOrderDetails(int orderID)
{
    NorthwindDataContext db = this.DataContext;
    IEnumerable<OrderDescription> orderDetails =
        from o in db.Orders
        where o.OrderID == orderID
        join s in db.Shippers on o.ShipVia equals s.ShipperID
        join od in db.OrderDetails on o.OrderID equals od.OrderID
        join p in db.Products on od.ProductID equals p.ProductID
        join supplier in db.Suppliers on p.SupplierID equals supplier.SupplierID
        let total = od.Quantity * od.UnitPrice
        select new OrderDescription {Product = p.ProductName, Quantity = od.Quantity, 
                     ShipperName = s.CompanyName, Total = total, UnitPrice=od.UnitPrice,
                     SupplierName = supplier.CompanyName};
    return orderDetails;

}

This code joins 5 tables to grab order details and adds the target fields to the custom OrderDescription object.  By using this code the SQL is created on the fly from LINQ expression trees and sent to the database so any changes to the query require changes to the code of course.  For those that don't like working with stored procedures this certainly is the next best thing.

A better way of doing this that leverages relationships between objects defined in the LINQ to SQL data model is shown next (thanks to Christian Nagel):

IEnumerable<OrderDescription> orderDetails =
  from o in db.Orders
  where o.OrderID == orderID
  from od in o.OrderDetails
  let total = od.Quantity * od.UnitPrice
  select new OrderDescription
  {
      Product = od.Product.ProductName,
      Quantity = od.Quantity,
      ShipperName = o.Shipper.CompanyName,
      Total = total,
      UnitPrice = od.UnitPrice,
      SupplierName = od.Product.Supplier.CompanyName
  };
return orderDetails;


Using Lambdas

I mentioned earlier that I'm a big fan of lambdas when a particular query is reasonable.  However, they can get out of control.  The fairly straightforward LINQ query shown above gets pretty nasty when switching to lambdas since the joins require identifying the primary, foreign keys and fields to select.  This is lambda overkill....there are too many => characters in there for me, but it matches up with the LINQ query shown above pretty well.

public override IEnumerable<OrderDescription> GetOrderDetails(int orderID)
{
    NorthwindDataContext db = this.DataContext;
      IEnumerable<OrderDescription> orderDetails =
        db.Orders.Where(order => order.OrderID == orderID).
        Join(db.Shippers, o => o.ShipVia, s => s.ShipperID, 
          (o, s) => new { o.OrderID, ShipCompanyName = s.CompanyName }).
        Join(db.OrderDetails, o => o.OrderID, od => od.OrderID, 
          (o, od) => new {o.ShipCompanyName, od.ProductID, od.Quantity, od.UnitPrice }).
        Join(db.Products, od => od.ProductID, p => p.ProductID, 
          (OrderDetails, p) => new { OrderDetails, p.ProductName, p.SupplierID }).
        Join(db.Suppliers, p => p.SupplierID, s => s.SupplierID, 
          (OrderData, s) => new { OrderData, SupplierName = s.CompanyName}).
        Select(o => new OrderDescription
        {
            Product = o.OrderData.ProductName,
            Quantity = o.OrderData.OrderDetails.Quantity,
            ShipperName = o.OrderData.OrderDetails.ShipCompanyName,
            Total = o.OrderData.OrderDetails.Quantity * o.OrderData.OrderDetails.UnitPrice,
            UnitPrice = o.OrderData.OrderDetails.UnitPrice,
            SupplierName = o.SupplierName
        });
    return orderDetails;
}

By leveraging relationships in the object model generated by the LINQ to SQL Designer you can simplify this query a lot.  Here's an example of doing that (thanks to Dug for commenting and posting the refactored version):

public override IEnumerable<OrderDescription> GetOrderDetails(int orderID)
{
       NorthwindDataContext db = this.DataContext;

       IEnumerable<OrderDescription> orders =
         db.Orders.Where(order => order.OrderID == orderID).
         Join(db.OrderDetails, o => o.OrderID, od => od.OrderID,
         (o, od) => new { ShipCompanyName = o.Shipper.CompanyName, 
                          od.ProductID, 
                          ProductName = od.Product.ProductName, 
                          Quantity = od.Quantity, 
                          UnitPrice = od.UnitPrice, 
                          SupplierName = od.Product.Supplier.CompanyName }).

                         Select(o => new OrderDescription
                         {
                             Product = o.ProductName,
                             Quantity = o.Quantity,
                             ShipperName = o.ShipCompanyName,
                             Total = o.Quantity * o.UnitPrice,
                             UnitPrice = o.UnitPrice,
                             SupplierName = o.SupplierName
                         });
       return orders;
}


Using LINQ with Stored Procedures

This is my favorite technique.  While LINQ makes it easy to query against a database without embedding inline SQL into C# or VB.NET, using pure LINQ code still doesn't provide the same level of security that stored procedures can provide, requires that SQL be generated dynamically from LINQ expression trees and can complicate application maintenance down the road in my opinion.  To call the stored procedure shown at the beginning of this post using LINQ to SQL techniques you can use the following code once the stored procedure has been drag and dropped onto the LINQ to SQL designer surface.  This code is simple and easy to maintain.  Plus, I can filter the results even more by using LINQ or by adding lambdas onto the ap_GetOrderDetailsByOrderID() method if needed.

public override IEnumerable<OrderDescription> GetOrderDetails(int orderID)
{
    IEnumerable<OrderDescription> orderDetails = DataContext.ap_GetOrderDetailsByOrderID(orderID);
    return orderDetails;
}

Ultimately it all comes down to personal preference.  Having worked through many LINQ, lambda and stored procedure queries I'll be sticking with LINQ to SQL with sprocs since the code is squeaky clean.  I have a few friends who prefer using inline LINQ as shown in the first example and we've argued the pros and cons of each technique back and forth.  The beauty of it all is that we get to use what we want and have multiple options to choose from!

I'll post the demo code I've been working on soon so those who are interested in getting into LINQ, lambdas and LINQ with sprocs can see how each technique can be used in an n-tier application architecture.

 

 

Posted on Sunday, February 17, 2008 at 10:43AM by Registered CommenterDan Wahlin in , , , | CommentsPost a Comment | EmailEmail | PrintPrint

How Would You Refactor this Code? #1

It's amazing how many different ways there are to accomplish the same task in code.  Talk to 2 developers and you'll almost always get two opinions.  That's part of what keeps it fun (and potentially why that guy in the other cube is constantly annoying you :-)).  In a previous post I wrote, there were several speed enhancement suggestions that were really good so I decided to start a "How Would You Refactor this Code" blog series to get opinions and see different approaches to coding. 

The first sample I wanted to post does a fairly simple string check to see if a string starts with a set of characters.  The value of the string being compared is variable.  There are multiple ways to do this that come to mind ranging from using a single string along with Contains(), regex, character by character comparisons, etc.  After a whole 10 seconds of thought I decided to go with a Lambda expression because I'm using Lambdas and LINQ a lot lately (and it's kind of fun).  It's not "the way" or the "best way" which is the point of this exercise.  So, how would you refactor this code?

string name = "mc_gross_1";  //The prefix and number are variable
string[] cartNames = { "item_number_", "item_name_", "mc_gross_", "quantity_" };
if (cartNames.Where(p => name.StartsWith(p)).Count() > 0)
{
    //process name
}


If you have refactoring ideas for this code or other "How Would You Refactor this Code" suggestions for future posts please add a comment. 

Code Refactoring Suggestions:

Here are some of the code refactoring suggestions to this point (read the comments for additional thoughts).  Great stuff.  If you have other suggestions keep them coming.

Suggestion # 1:

if (cartNames.Any(p => name.StartsWith(p)))
{
    //process name
}


Rationale for this refactoring:

You need only to know if the name is found in the array.  In this case the extension method Any() will do the best job for you.

The solution with Where() and Count() is not good. With Any() at the first match you will have the result and with Where() you will traverse the entire collection and then Count() the items.

Note 1: Count() is an extension method not a property so it has a complexity of O(n).

Note 2: Where() will create a collection to store matches(allocating memory). Any() will return a simple bool.

More semantically correct, because you're not really interesting in counting - just existence - it also has the added bonus of being more succinct.

Fabrice Marguirie was one of several people that suggested this refactoring.  I just purchased the EBook version of his LINQ in Action book and have found it to be very good so far.

Suggestion #2:

//C# 3.0
if (Array.Exists(cartNames, p => name.StartsWith(p)))
{
    // Process name
}

//C# 2.0
if (Array.Exists(cartNames, delegate(string p)
{
    return name.StartsWith(p);
}))
{
    // Process name
}


Rationale for this refactoring:

The most obvious suggestion is to use the .NET 2.0 "Array.Exists" method, rather than a .NET 3.5 LINQ query. Aside from the problem that many PCs don't have .NET 3.5 installed yet - and you can't install it on Windows 2000 - the Exists method can be more efficient than a count, as it will stop after the first match, rather than continuing to the end of the list.

Suggestion #3:

string name = "mc_gross_1";  //The prefix and number are variable
if (new Regex(@"(item_number_|item_name_|mc_gross_|quantity_)\d").Matches(name).Count > 0)
{
    // Process name
}

List<string> cartNames = new List<string>(new string[] { "item_number_", "item_name_", "mc_gross_", "quantity_" });
if (cartNames.Contains(name.Substring(0, name.LastIndexOf("_") + 1)))
{
    // Process name
}


Rationale for this refactoring:

JV (and colleagues) focused on how to solve this coding issue without using LINQ.

Suggestion #4:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;

public sealed class StringPrefixComparer : IComparer<string>, IComparer
{

    private readonly CompareInfo _compareInfo;
    private readonly CompareOptions _options;

    private StringPrefixComparer(CompareInfo compareInfo, CompareOptions options)
    {
        _compareInfo = compareInfo;
        _options = options;
    }

    public static StringPrefixComparer Ordinal
    {
        get
        {
            return new StringPrefixComparer(
                CultureInfo.InvariantCulture.CompareInfo,
                CompareOptions.Ordinal);
        }
    }

    public int Compare(string x, string y)
    {
        if (string.IsNullOrEmpty(x)) return (string.IsNullOrEmpty(y)) ? 0 : -1;
        if (string.IsNullOrEmpty(y)) return 1;
        int length = (x.Length > y.Length) ? y.Length : x.Length;
        return _compareInfo.Compare(x, 0, length, y, 0, length, _options);
    }

    int IComparer.Compare(object x, object y)
    {
        return this.Compare(x as string, y as string);
    }

}

static class Program
{

    static bool Exists<T>(this T[] list, T item, IComparer<T> comparer)
    {
        return 0 <= Array.BinarySearch(list, item, comparer);
    }

    static void Main()
    {

        string[] cartNames = { "item_name_", "item_number_", "mc_gross_", "quantity_" };
        Array.Sort(cartNames, StringComparer.Ordinal);
        string name = "mc_gross_1";
        if (cartNames.Exists(name, StringPrefixComparer.Ordinal))
        {
            // Process name
        }
    }
}

Rationale for this refactoring:

Assuming that the array of prefixes is constant, ensure that the array is sorted, and use the Array.BinarySearch() method with a custom IComparer<string> implementation.  Uses the new C# 3.0 extension method capability and does a clever trick in the Compare() method that avoids having to explicitly worry about stripping off the numeric character on the end of the name variable.   Thanks to Richard for taking the time to post this one.

 

Posted on Wednesday, January 30, 2008 at 06:07PM by Registered CommenterDan Wahlin in | CommentsPost a Comment | EmailEmail | PrintPrint

C# 3.0 Features: Extension Methods

.NET 3.5 is out which means all of the great features available in C# 3.0 are available to use now.  Here's a quick list of the main language enhancements available in C# 3.0:

  • Object Initializers
  • Automatic Properties
  • Extension Methods
  • Anonymous Types
  • Lambda Expressions
  • LINQ
  • Collection Initializers

    Extension methods allow existing classes to be extended without relying on inheritance or having to change the class's source code.  This means that if you want to add some methods into the existing String class you can do it quite easily.  Here's a couple of rules to consider when deciding on whether or not to use extension methods:

    • Extension methods cannot be used to override existing methods

    • An extension method with the same name and signature as an instance method will not be called

    • The concept of extension methods cannot be applied to fields, properties or events

    • Use extension methods sparingly....overuse can be a bad thing!

    Here's an example of creating an extension method in C# that adds a RemoveNonNumeric() method to the String class.  Notice that the class is defined as static as well as the extension method itself.  The "this" keyword in the parameter signature tells the compiler to add the extension method to the String class since "string" follows the keyword.

    namespace StringExtensions
    {
        public static class StringExtensionsClass
        {
            public static string RemoveNonNumeric(this string s)
            {
                MatchCollection col = Regex.Matches(s, "[0-9]");
                StringBuilder sb = new StringBuilder();
                foreach (Match m in col)
                    sb.Append(m.Value); 
                return sb.ToString();
            }
        }


    Here's an example of how the extension method can be used.  You'll see that the namespace for the extension method class is imported.  From there, the compiler treats the RemoveNonNumeric() method as if it was originally part of the standard System.String class. 

    using StringExtensions;
    


    .... string phone = "123-123-1234"; string newPhone = phone.RemoveNonNumeric();

  • Update:  Although the overall point of the post was to simply show how to create extension methods, Andrex posted a more efficient way to remove non-numeric characters for those that may actually need that specific functionality (I'll admit I was just throwing something out there :-)).  Thanks for commenting Andrex!

    public static string RemoveNonNumeric(this string s)
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < s.Length; i++)
            if (Char.IsNumber(s[i]))
                sb.Append(s[i]);
        return sb.ToString();
    }
    del.icio.us Tags: ,

     

    Posted on Friday, January 25, 2008 at 02:15PM by Registered CommenterDan Wahlin in , | CommentsPost a Comment | EmailEmail | PrintPrint

    Upcoming .NET Courses in 2008



    I've had several people here in the Phoenix area and others I've met at ASP.NET Connections conferences ask when I'll be teaching specific .NET classes in 2008 and my standard reply has been "I'm not sure at this point".  We have things scheduled out past June now so here's the information for those who are interested.  Most of the classes listed are 5 days aside from the First Look at Visual Studio 2008 (1 day) and ASP.NET AJAX Programming (3 days).

    The schedule is of course subject to change, but it's what I have at this point.  If you have any questions about any of the courses feel free to contact me through my blog.

    Posted on Thursday, January 10, 2008 at 09:49PM by Registered CommenterDan Wahlin in , , , , , , , | CommentsPost a Comment | EmailEmail | PrintPrint

    C# 3.0 Features: Automatic Properties

    .NET 3.5 is out which means all of the great features available in C# 3.0 are available to use now.  Here's a quick list of the main language enhancements available in C# 3.0:

  • Object Initializers
  • Automatic Properties  
  • Anonymous Types
  • Extension Methods
  • Lambda Expressions
  • LINQ
  • Collection Initializers
  • One of the things I can't say that I've enjoyed doing in the past when writing .NET classes was creating properties and associated fields.  I leveraged the "prop" code snippet a lot in Visual Studio 2005 so that I didn't have to type much, but I still had to go through and define the field name and property name in the code.  While public fields could certainly be used in some cases, they don't provide any control over the data being assigned (especially if the field is a string type) and aren't supported well when it comes to data binding.  As a result I always create public properties to wrap fields even if I don't have any "extra" logic that needs added into the get or set blocks.  Here's the standard way of creating fields and properties using C# 2.0:

    public class Person 
    {    
       
    string _FirstName;
       string 
    _LastName;

       public string 
    FirstName 
       {
            
    get return _FirstName}
            
    set { _FirstName = value; }
       }

       
    public string LastName 
       {
            
    get return _LastName}
            
    set { _LastName = value; }
       }
    }

    With C# 3.0 a new feature called "automatic properties" is now available.  When you use the "prop" code snippet in Visual Studio 2008 you'll see that empty get and set blocks are added and that no associated field is added into the code.  The compiler will automatically generate the backing field at compile time if it finds empty get or set blocks saving you the work. You can still add get and set blocks that have additional filtering logic in them as well although you'll have to type all of that yourself of course. 

    Here's an example of how properties can be written in C# 3.0....you gotta love it especially when you compare how much more compact this technique is compared to the older way of doing things.

    public class Person 
    {    
       
    public string FirstName  { get; set; }
       
    public string LastName  { get; set; }

    Posted on Tuesday, December 4, 2007 at 01:02PM by Registered CommenterDan Wahlin in | CommentsPost a Comment | EmailEmail | PrintPrint

    C# 3.0 Features: Object Initializers

    C# 3.0 is just around the corner so I thought I'd start writing about a few of the features that it exposes and provide quick and concise examples of how they can be used.  Many of the new features rely on the compiler to generate code that you would have had to write in the past. This can result in significantly less code compared to C# 2.0 syntax in many cases.  Here's a list of some of the key features available in C# 3.0:

    • Object Initializers
    • Anonymous Types
    • Automatic Properties
    • Extension Methods
    • Lambda Expressions
    • LINQ
    • Collection Initializers

    In this post I'll discuss the fundamentals of object initializers in C# 3.0.  To get started, let's look at the standard way of initializing an object with data in C# 2.0 using constructors.  The following example creates a Person object and passes three values to its constructor.

    Person p = new Person("John", "Doe", "602-123-1234");

    As mentioned, C# 3.0 now supports the concept of "object initializers" which means you can easily assign data to specific properties in a type with having to create an explicit constructor (you can of course still create constructors as well). The standard C# { and } brackets are used to create object initializers.  Here's an example of using an object initializer to assign property data to a Person type.  It's nice because doing the same thing without using a constructor in C# 2.0 would have resulted in around 5 lines of code which is too many for something simple like property value assignments.

    Person p = new Person() {FirstName="John",LastName="Doe",Phone="602-123-1234",City="Phoenix"};

    If the Person type defines a sub object as a property you can even use object initializers to create the sub object. Here's an example of defining an Address object:

    Person p = new Person() 
    {
    FirstName = "John",
    LastName = "Doe",
    Address = new Address()
    {
    Street = "1234 St.",
    City = "Phoenix"
    }
    };


    If you've used JavaScript Object Notation (normally referred to as JSON) in AJAX or other client-side applications, you'll recognize this style of syntax.  It's simple, compact, and easy to use.  Although I formatted the example above onto multiple lines to maximize readability, it could certainly be compacted quite a bit if desired. 

    In the next post I do on C# 3.0 features I'll cover anonymous types and explain how they answer a question I'm often asked in .NET language classes I teach:  "Why do I have to define a type name twice when creating an object?".

    Posted on Sunday, September 9, 2007 at 10:21PM by Registered CommenterDan Wahlin in | CommentsPost a Comment | EmailEmail | PrintPrint

    The Power of C# Anonymous Methods

    Anonymous methods are a new feature in C# 2.0 that allow you to hook an action directly to an event as opposed to having a separate event handler.  For example, when a user clicks a button and you need to pop-up a MessageBox, you could handle it the standard way with a delegate and an event handler, or you could hook the action to perform directly to the Click event using an anonymous method as shown next:

    btnSubmit.Click += delegate(object sender,EventArgs e)
    {
        MessageBox.Show(
    "Thanks for clicking the button!");
    });

    Looking through the code you'll see that no method name is given to the inline event handler method.  Instead it uses the delegate keyword and defines the parameters that the event handler would normally expect. 

    I've not a big fan of using anonymous methods for things like button clicks, DropDownList SelectedIndexChanged events, etc. although they're certainly valid in those scenarios.  Where I do think anonymous methods are quite useful is in situations where a collection needs to be quickly sorted and I don't feel like implementing the IComparable<T> interface on the class (or creating a custom sort class with IComparer<T>).  There are many other examples of where they could be used as well such as with Array.ForEach()<T>, etc.  Basically, anytime you see a method that accepts a delegate as a parameter you could use anonymous methods.

    To see how anonymous methods can be used for sorting, assume that you have the following Customer class defined and you'd like to easily sort a list of Customer objects based on Name, Age or CustomerSince (date):

    public class Customer
    {
        
    private DateTime _CustomerSince;
        private int 
    _Age;
        private string 
    _Name;

        public 
    DateTime CustomerSince
        {
            
    get return _CustomerSince}
            
    set { _CustomerSince = value; }
        }

        
    public int Age
        {
            
    get return _Age}
            
    set { _Age = value; }
        }

        
    public string Name
        {
            
    get return _Name}
            
    set { _Name = value; }
        }
    }

    You can sort a List<Customer> based upon different criteria by using anonymous methods and the Comparer<T> class.  Here's an example of performing different types of sorts using anonymous methods and the List<T> Sort() method.  By using this technique you write a minimal amount of code and keep it concise since the delegate and handler are defined together.

    static void Main(string[] args)
    {
        List<Customer> custs 
    = new List<Customer>();
        
    Customer cust1 = new Customer();
        
    cust1.Age 35;
        
    cust1.Name "John Doe";
        
    cust1.CustomerSince = new DateTime(200011);

        
    Customer cust2 = new Customer();
        
    cust2.Age 33;
        
    cust2.Name "Jamie Doe";
        
    cust2.CustomerSince = new DateTime(200641);

        
    Customer cust3 = new Customer();
        
    cust3.Age 10;
        
    cust3.Name "Jane Doe";
        
    cust3.CustomerSince = new DateTime(199921);

        
    custs.Add(cust1);
        
    custs.Add(cust2);
        
    custs.Add(cust3);

        
    Console.WriteLine("Sorting by CustomerSince date:");
        
    custs.Sort(delegate(Customer c1, Customer c2)
        {
            
    return Comparer<DateTime>.Default.Compare(c1.CustomerSince, 
                c2.CustomerSince)
    ;
        
    });

        foreach 
    (Customer cust in custs)
        {
            Console.WriteLine(cust.Name + 
    " " 
                cust.CustomerSince.ToShortDateString())
    ;
        
    }

        Console.WriteLine(
    "\r\nSorting by Age:");
        
    custs.Sort(delegate(Customer c1, Customer c2)
        {
            
    return Comparer<int>.Default.Compare(c1.Age, c2.Age);
        
    });

        foreach 
    (Customer cust in custs)
        {
            Console.WriteLine(cust.Name + 
    " " + cust.Age.ToString());
        
    }
        Console.Read()
    ;
    }

    In addition to using anonymous methods, this code relies upon the Comparer<T> generic class to specify the type that should be sorted as well as the objects to compare.  Although I used standard foreach loops above, anonymous methods could've been used to accomplish looping as well if I really wanted to go wild with them.

    If you find yourself doing this type of sorting a lot you may want to explore creating a custom class that implements the IComparable<T> interface. However, in cases where you just need to perform a sort quickly and easily, anonymous methods are very useful.  The code shown in this example can be download here.

    Posted on Saturday, April 21, 2007 at 10:50AM by Registered CommenterDan Wahlin in | CommentsPost a Comment | EmailEmail | PrintPrint

    C# Programming Class Samples

    I just finished up the C# 2.0 Programming course at Interface Technical Training and wanted to get some of the code posted that we did today covering events and delegates and ADO.NET.  Thanks to everyone who attended.  It was a really fun week.

    C# Examples

    Posted on Thursday, March 8, 2007 at 03:36PM by Registered CommenterDan Wahlin in | CommentsPost a Comment | EmailEmail | PrintPrint

    Video: Creating Custom Events and Delegates with C#

    It's no secret that events and delegates play a crucial role in the .NET framework. Without them it would be hard to handle user input or notify other objects when an action occurs. I get a lot of questions about events and delegates in classes I teach so I decided to put together a video that outlines the fundamentals of creating a custom class that exposes an event and a delegate. The video also demonstrates how to create a custom EventArgs class and how events can be consumed using C#. The code shown in the video can be downloaded here.

     

    Posted on Thursday, January 18, 2007 at 12:51AM by Registered CommenterDan Wahlin in , | Comments15 Comments | EmailEmail | PrintPrint

    Nullable Types in C# 2.0

    I'm teaching a C# 2.0 class at Interface Technical Training this week and thought I'd blog about two features I really like in C# 2.0 that save some typing (although they may arguably lead to more cryptic code) and are really useful.  Sure, there's all the goodness associated with generics, anonymous methods, partial types, etc. in C# 2.0 but two nice language enhancements are nullable types (which relate to generics) and the ?? operator.  If you've ever retrieved a null value from a database and then tried to assign it to an int or DateTime variable then you'll definitely appreciate nullable types if you haven't already used them.

    Nullable types can be defined in different ways. The first is using the Nullable<T> struct which is new in .NET 2.0:

    //Call a DB routine that may return a C# null value (not DBNull.Value) 
    Nullable<
    int> age GetAge()

    While this works, I prefer the following syntax which is the same as the code above but more compact:

    //Call a DB routine that may return a C# null value (not DBNull.Value)
    int
    ? age GetAge()

    I also like the ?? operator since it provides a compact way to check if a variable is null.  If the value is null then a default value can be returned.  Instead of the writing the following code to check for nulls (which uses short-cut conditional logic):

    int? age = GetAge();
    int
    ? tempAge (age==null)?-1:age;

    I could instead use the ?? operator:

    int? age = GetAge();
    int? 
    tempAge age??-1;

    The code that uses the ?? operator says that if age isn't null then assign it to tempAge.  If age is null then assign tempAge a value of -1.  Some may argue that this makes code too cryptic (and they'd have a point).  But, I like compact coding solutions.  Besides....it's not nearly as bad as writing regular expressions. :-)

     

    Posted on Tuesday, October 24, 2006 at 04:34PM by Registered CommenterDan Wahlin in | Comments1 Comment | EmailEmail | PrintPrint