Wednesday, October 17, 2007

LINQ - extension methods in action


As promised in one of previous posts - more about extension methods. Let's have a look at... LINQ!


You remember extension methods, whose simplest definition would be:
Extension methods are basically static methods that are callable through an instance syntax
[The Evolution Of LINQ And Its Impact On The Design Of C#]

It seems like they were introduced in C# 3.0 to make LINQ work fully.

LINQ is a language feature allowing to query collections in a SQL-like manner (SELECT statement), something like:
var locals = from c in customers
where c.ZipCode == 91822
select new { FullName = c.FirstName + “ “ +
c.LastName, HomeAddress = c.Address };


So - where are extension methods here?

Well - the sample above is actually syntactic sugar, being equivalent to:
var locals =
customers
.Where(c => c.ZipCode == 91822)
.Select(c => new { FullName = c.FirstName + “ “ + c.LastName,
HomeAddress = c.Address });

Now, let's assume customers are of type IEnumerable<Customer>. IEnumerable<T> has only one method: GetEnumerator<T>. This means that both Where and Select must be extension methods, which mix the SQL-like functionalities into all IEnumerable<T>-s!

In fact the Where method is very simple:
class EnumerableExtensions
{
public delegate T Func(A0 arg0);

public static IEnumerable Where(this IEnumerable source, Func predicate)
{
foreach (T element in source)
{
if (predicate(element)) yield return element;
}
}
}

It takes the IEnumerable<T> source parameter - which is preceded by the this keyword (so it's going to extend the IEnumerable<T> type), and the predicate delegate.
It can then use the predicate to tell whether each element in the source satisfies the "WHERE clause".
Those, that do - are put into the resulting collection of the Where method (using the yield keyword).

So, basically the following:
customers.Where(c => c.ZipCode == 91822)

will result in calling the static Where method against the customers object, with the Func<T, bool> predicate set to this anonymous method:

delegate {
if (c.ZipCode == 91822) yield return c;
}

Yep, that's what happened to the:
c => c.ZipCode == 91822
thing, which is actually a lambda expression - another syntactic sugar in C# 3.0, on which more some other time.

Sunday, October 7, 2007

Interview Questions: Constructors in C#


A good interview-type question: constructors in C#.


Here's a good one for an interview (whether you're the interviewer or the interviewee):

When declaring a constructor in the subclass, should I explicitly call the base class's constructor?
And if I don't - will the base class's constructor get called anyway?

That's basically what a discussion between my friend Marcin and me got down to...

If you've ever used Resharper (don't tell me you haven't!), you might have noticed that when you go:
class SubClass : BaseClass
{
public SubClass() : base()
{
// some code here
}
}
it will gray out base(), because it is redundant.

And it's true - because if the base constructor wasn't called, the object might not get fully initialized - and that would in a sense break the Liskov's Substitution Principle...

Actually - you do not have to "agree" for the base parameterless constructor to be invoked. You can choose a different one instead:
public SubClass() : base(5)
{
// some code here
}

However - if you look at this summary C# Constructors:
There must always be a "chain" of constructors which runs constructors all the way up the class hierarchy. Every class in the hierarchy will have a constructor invoked, although some of those constructors may not explicitly appear in the code.

All clear now, eh? ;)

Monday, October 1, 2007

Extension Methods in C# 3.0


This is actually "old stuff" today - but it is really cool: extension methods in C# 3.0 and mixins!


Ever wanted to raise a double to the power of another double without having to go like:
Math.Pow(10.343, 302.34);
?

Well, what do you say for that:
(10.343).RaiseToPower(302.34);


That would be very nice, and... it is possible, as long as:

  • you are using C# 3.0

  • you have implemented an extension method like this:

  •     public static class Powerade
    {
    public static double RaiseToPower(this double x, double y)
    {
    return Math.Pow(x, y);
    }
    }

    This is of course a quite useless example, but what extension methods are in essence is a way to implement mixins in C# 3.0: you can "mix in" some functionality to a type that is already there.

    More on mixins soon.

    Monday, September 24, 2007

    MERGE Statement in SQL Server


    Ever had to merge two tables in SQL? Hard work?
    The MERGE statement is only available in SQL Server 2008 (and Oracle and DB2 ;) ), but in the meantime - you can mimic it.


    If you ever had a large csv file with a new version of data already contained in a table in SQL, you dreamed of something like this, didn't you:

    MERGE t1
    USING (SELECT @id AS id, @name1 AS name1) AS t2 ON t1.id = t2.id
    WHEN MATCHED
    THEN UPDATE SET t1.name1 = t2.name1
    WHEN NOT MATCHED
    THEN INSERT VALUES(@id, @name1)
    In other words: if the id of a row in the new version matches one in the old version - update the old row; otherwise - insert a new row.

    [Of course we're assuming here that you managed to load the contents of the csv file into a staging table].

    Well, if you have the luxury of working with SQL Server 2008, the construct above is exactly what you could use there. Have a look here: Using MERGE statement.


    Now, since SQL Server 2008 is not yet used in too many commercial projects ;) - it is often the case that you have to implement such functionality on your own.

    According to Alex Kuznetsov (MVP):
    In SQL Server 2005 you can use OUTPUT clause of an UPDATE statement
    in order to achieve that.

    See for yourself:
    declare @updated_ids table(id int)

    update permanent set d=s.d, comment = 'Modified Row'
    output inserted.id into @updated_ids
    from permanent p, staging s
    where p.id=s.id

    insert into permanent
    select id, d, 'New Row' from staging where id not in(select id from @updated_ids)
    go
    Pretty neat!

    You can find Alex's whole post here: Mimicking MERGE Statement in SQL 2005.

    Tuesday, September 18, 2007

    Parsing Xml with a Default Namespace Defined


    What's that namespace doing there?


    I recently answered a question on MS newsgroups regarding navigating an XML document whose fragment is below:
    <?xml version="1.0" encoding="UTF-8"?>
    <JMF xmlns="http://www.CIP4.org/JDFSchema_1_1" Version="1.2"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Response ID="RDFS1934507113653e9" ReturnCode="0" Type="QueueStatus"
    refID="132413dj323s223" xsi:type="ResponseQueueStatus">
    <Queue DeviceID="Dev01" QueueSize="8" Status="Waiting">
    <QueueEntry DeviceID="vl-5001" JobID="1048655" JobPartID="79">



    The author of the question wanted to get to the QueueEntry using the following XPath expression:
    JMF/Response/Queue/QueueEntry
    Unfortunately - it returned no XmlNodes (when used in xmlDoc.SelectNodes(...)).

    And here's why:
    <JMF xmlns="http://www.CIP4.org/JDFSchema_1_1" ...
    This means that all children of the <JMF> are in the "http://www.CIP4.org/JDFSchema_1_1" namespace.
    So if you try to reference them without specifying that namespace, you are actually trying to reference some nodes that do not exist in the document!

    Here's what you have to do to be able to select those nodes:
    XmlDocument xmlDoc = new XmlDocument(); 
    xmlDoc.LoadXml(doc);

    XmlNamespaceManager nm = new
    XmlNamespaceManager(xmlDoc.NameTable);
    nm.AddNamespace("my", "http://www.CIP4.org/JDFSchema_1_1");

    XmlNodeList list =
    xmlDoc.SelectNodes("/my:JMF/my:Response/my:Queue/my:QueueEntry", nm);
    foreach (XmlNode node in list)
    {
    string sID = node.Attributes["DeviceID"].Value;
    }
    Yeah, it looks a little bit cumbersome, but it works! :)

    Monday, September 17, 2007

    How to Execute a SQL Script from .NET Code?


    The old days of splitting scripts by the GO statement or using osql are over! SMO is here!


    It happens from time to time that you need to execute a T-SQL script - e.g. you are writing a database update manager or whatever.

    And it's always the old problem of the 'GO' separator, isn't it? ADO.NET just won't swallow it!

    The solution was always to either use some external tool (like osql or sqlcmd) to execute the script or to parse the script for all the 'GO'-es. But both those methods were kind of... not perfect.

    The good news is - you don't have to worry about it anymore!

    If you have a closer look at SQL Server Management Objects (SMO), you will find the following method:
    Server.ConnectionContext.ExecuteNonQuery()
    which can actually do all the job for you!


    If course it is only available in SQL Server 2005. But isn't that what progress is all about - new things have more features than old ones? ;)


    You can find the SMO assemblies here:
    C:\Program Files\Microsoft SQL Server\90\SDK\Assemblies
    if you have SQL Server 2005 installed on your machine.

    Friday, September 14, 2007

    overloading operator==


    Beware of infinite recursion when overloading the == operator!


    When you overload the equality operator (==) in C#, you should of course remember that:

  • you should also overload operator !=

  • the operator's implementation should not throw exceptions


  • Having to overload the unequality operator (!=) as well is rather obvious. Saying:
    a != b
    is another way of saying:
    !(a == b)

    The second point is not unusual, either. No one would rather expect an operator to throw an exception - otherwise, you'd have to put every other if statement in a try-catch block.

    And what would you actually do with a "CouldNotCheckForEqualityException" anyway? It's not a kind of error you'd expect at runtime, is it? If you can't check two objects for equality - you would rather like to know that at compile time!


    Now - in order to protect yourself from throwing an exception in the implementation of the == operator, you should check its arguments for being null, so that you can safely access their fields for comparison purposes.

    Oh, that's simple, isn't it?
    if (x == null)
    return y == null;
    else
    return x.Equals(y);

    Pretty clever, eh? But this will NOT work, unfortunately!
    Note that the two comparisons to null will actually call the overloaded == operator, causing an infinite recursion!

    There are actually two ways of fixing that:

  • you could call x.ReferenceEquals(null) - not too elegant for me, or
  • you could cast the arguments to objects:
    if ((object) x == null)
    return (object) y == null;
    else
    return x.Equals(y);

    And that's what I call a really clever and slick piece of code :)
    Thanks go to the author of this post for sharing it:
    Re: Overloading operator== and comparing to null

    Oh, and of course the implementation of the != operator would be:
    return !(x == y)
  •