posts filed under "November 2007 Entries"
(.)

With the final version of Visual Studio 2008 released recently, a couple of helpful add-ons were made available by Microsoft but are sometimes somewhat hidden. One of these is the Expression Tree Visualizer. Here is a direct download link containing the source code and the compiled version - you will also find the project in your Program Files\Microsoft Visual Studio 9.0\Samples\1033\CSharpSamples.zip\LinqSamples\ExpressionTreeVisualizer folder.

Once you've either downloaded or built the visualizer, shut down all running instances of Visual Studio 2008 and copy ExpressionTreeVisualizer.dll from the LinqSamples\ExpressionTreeVisualizer\ExpressionTreeVisualizer\bin\Debug directory to Program Files\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\Visualizers.

The next time you hover over a Lambda Expression in Debug mode you'll see a little magnification glass:

image

Once you click on it, the Expression Tree Visualizer will nicely display the underlying Expression Tree to you:

image

Cool, or?

(While you're here, you might be interested into the LINQ to SQL Debug Visualizer, too!)

 



In part 1 of this mini series I described a solution which involved adding the System.Linq.Dynamic namespace provided as an extra download by Microsoft. While it is a perfectly legal way of solving a dynamic predicates problem in LINQ, it actually comes at a cost: You're losing some of LINQ's type safeness and explicit beauty.

So in this second part I cover another way of achieving the same goal based on LINQ's Expression tree capabilities. In a nutshell Expression trees allow you to compose complex expression programmatically which you can then use as an input for LINQ queries. The framework classes to deal with Expression trees can be found in the System.Linq.Expressions namespace. Expression trees are a concept found in many functional languages and it took quite a while until I've been able to wrap my brain around them. Don't worry if you do not get everything exactly right from the very beginning.

Let's start with reiterating the problem:

Suppose you've got a list of keywords stored as strings in a collection. You want to use LINQ to SQL along with the sample Northwind database to select all customers where the ContactName contains at least one of the keywords. In "static" LINQ you would possibly write the following query:

code

var query = from c in db.Customers

            where (c.ContactName.Contains("Maria")) || (c.ContactName.Contains("Pedro"))

            select c;

 

But how do you handle a situation where the list of search terms ("Maria", "Pedro", etc.) is unknown at compile time?

You might feel tempted to compose the following LINQ query:

code

var query = from c in db.Customers

            where c.ContactName.Contains("Maria")

            where c.ContactName.Contains("Pedro")

            select c;

 

Unfortunately this query will select all rows where ContactName contains "Maria" and "Pedro", as the generated SQL reveals:

SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]
WHERE ([t0].[ContactName] LIKE '%Pedro%') AND ([t0].[ContactName] LIKE '%Maria%')

To solve the problem in a reusable way what we need is a mechanism to dynamically compose a Lambda expression at runtime based on a given list of search terms.

I've added a class PredicateExtensions to my solution:

code

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Linq.Expressions;

 

namespace www24100net.PlayingWithLinq

{

    public static class PredicateExtensions

    {

        public static Expression<Func<T, bool>> True<T>() { return f => true; }

        public static Expression<Func<T, bool>> False<T>() { return f => false; }

 

        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expression1,

                                                            Expression<Func<T, bool>> expression2)

        {

            var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());

            return Expression.Lambda<Func<T, bool>>

                  (Expression.Or(expression1.Body, invokedExpression), expression1.Parameters);

        }

 

        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1,

                                                            Expression<Func<T, bool>> expression2)

        {

            var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());

            return Expression.Lambda<Func<T, bool>>

                  (Expression.And(expression1.Body, invokedExpression), expression1.Parameters);

        }

    }

}

 

It implements two static methods True() and False() which merely serve as a point to start with once you construct a PredicateExtension and two extension methods Or() and And(). Please note the "this" keyword in the parameter list which marks Or() and And() as extension methods on the Expression type implemented inside the System.Linq.Expressions namespace.

And here is a sample use of the new extension methods:

code

            NorthwindDataContext db = new NorthwindDataContext();

 

            string[] searchTerms = new string[] { "Maria", "Pedro" };

 

            var predicate = PredicateExtensions.False<Customer>();

 

            foreach (string searchTerm in searchTerms)

            {

                string temp = searchTerm;

                predicate = predicate.Or(c => c.ContactName.Contains(temp));

            }

 

            dataGridView1.DataSource = db.Customers.Where(predicate);

 

Note how inside the foreach loop we are dynamically composing a Lambda expression based on the added Or() extension method!

The Expression tree created at runtime and handed to the LINQ to SQL parser looks as follows:

predicate = {f => ((False Or Invoke(c => c.ContactName.Contains(value(www24100net.PlayingWithLinq.MainForm+<>c__DisplayClass0).temp),f)) Or Invoke(c => c.ContactName.Contains(value(www24100net.PlayingWithLinq.MainForm+<>c__DisplayClass0).temp),f))}

Wow... pretty wild code, or? Fortunately the LINQ to SQL stack knows how to parse this into highly efficient SQL. The SQL command created by LINQ to SQL based on the above tree:

'SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]
WHERE ([t0].[ContactName] LIKE @p0) OR ([t0].[ContactName] LIKE @p1)',N'@p0 nvarchar(7),@p1 nvarchar(7)',@p0=N'%Maria%',@p1=N'%Pedro%'

That's exactly what we were looking for!

I'm planning to create an in-depth series about Expression trees where I start with the basics and move forward to advanced dynamic Expression tree composition. In the meanwhile I hope this helps moving forward.

 


In many LINQ (to SQL) related posts questions regarding the dynamic construction of LINQ queries arise. Most of the available answers deal with using LINQ's Expression classes to construct an expression tree at runtime. While this definitely is an elegant way, it's also extremely difficult for most object oriented programmers to understand. I'd therefore provide a little bit of an easier solution which simply constructs the where constraint from a string.

I admit that this takes away some of LINQ's type safeness and beauty and goes closely to creating an SQL command on the fly, however, it's inspired by a post from Anders Hejlsberg, the inventor of LINQ, so I assume it's not too wrong. ;-)

Here's the problem:

Suppose you've got a list of search terms which might vary at runtime and you want to declare a LINQ to SQL query which returns all Customers from the Nortwhind database, where the ContactName contains any of the search terms.

Here is the LINQ to SQL query that does exactly that:

code

string[] searchTerms = new string[] { "Maria", "Pedro" };

string search = "";

 

foreach (string searchTerm in searchTerms)

{

    search += "ContactName.Contains(\""+searchTerm+"\") or ";

}

 

search += "1=0";

 

var query = db.Customers.Where(search).Select(c => c);

 

It's very straight forward: In the foreach loop we are concatenating a string which will serve as the condition for the where clause. In the above example this will evaluate to:

ContactName.Contains(\"Maria\") or ContactName.Contains(\"Pedro\") or 1=0

The "1=0" is only there because otherwise search would end with an "or" operator once the loop finishes and LINQ would not be able to parse it.

Before you copy and try to compile: Obviously the shipping version of LINQ to SQL does not support any overload for the Where extension method, that takes a single string parameter as its argument. In order to make the above compile you have to download and include further extension methods for LINQ from Microsoft. Once you've downloaded expand the archive and include the System.Linq.Dynamic namespace contained within the Dynamic.cs file LinqSamples\DynamicQuery\DynamicQuery.

I wondered why these methods did not make it into the final shipping build of LINQ but am happy that I finally found them!

Hope this helps!

 


On the German MyCSharp forums I recently stumbled across a question as to how to trace the actual SQL statement generated by the LINQ to SQL extension methods. This pretty powerful feature which I've used quite a lot during my first weeks with LINQ is in deed a bit hidden inside Visual Studio 2008.

Suppose you've got the following code which executes a LINQ query against the famous Northwind sample database and binds the results to a WinForms DataGrid:

code

var query = from c in db.Customers

            where searchTerms.Contains(c.ContactName)                           

            select c;

 

The trick is to insert a breakpoint before the query gets executed for the first time. (Remember: LINQ queries get executed once they get used for the first time. In the above example the database does not get accessed at the var assignment!)

Once the breakpoint is hit during execution, Visual Studio will break out to the debugger. If you hover over the query statement, IntelliSense displays the SQL statement generated based on your LING query:

image

Visual Studio 2008 goes even further. If you click the little magnifying glass, it opens the LINQ to SQL debug visualizer which allows you to inspect the raw SQL generated by the OR/M:

image

You can even execute the query while you're debugging to see the results returned by the database:

image

The LINQ to SQL debug visualizer is not included in the RTM version of Visual Studio 2008. You can get it as a separate download. To install the LINQ to SQL debug visualizer, follow the below steps:

1) Shutdown all running versions of Visual Studio 2008.

2) Copy the SqlServerQueryVisualizer.dll assembly from the \bin\debug\ directory in the .zip download above into your local \Program Files\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\Visualizers\ directory.

That's it! Now you'll see the little magnifying glass which allows you to drill into the SQL query.

One last note: If you execute ToString() on the LINQ to SQL query you also get the SQL statement. So supposed we've got a TextBox control named txtLog in our WinForms application, this code:

code

txtDebug.Text = query.ToString();

 

would print out the SQL statement as seen with Visual Studio type inspector!

 


A couple of days ago I expressed my disappointment about the beta 2 version installers of the Entity Framework installers not working with Visual Studio 2008 RTM. Soon after my initial post I blogged about a quick and dirty workaround which involved "hacking" the Entity Framework installer. Thanks to a comment submitted by James Story the following solution will allow you to install the Entity Framework Tools CTP with Visual Studio 2008 RTM.

Please be aware that the ADO.NET team is planning to release an updated version of the Entity Framework which will work with Visual Studio 2008 RTM, soon - according to an email from Scott Guthrie. So while these workarounds get you started, you should regularly check the ADO.NET Team's blog.

In order to install the Entity Framework Tools CTP you have to change a signature in the installer. In order to do so you need the Orca tool burdened in the Core Platform SDK. Aaron Stebner (in general a great resource when it comes to installation issues with a whole list of Microsoft products) provides a direct download link to the utility. Once downloaded and installed open the dp_entitydatamodeltools.msi installer via File > Open.

Select the Signature table and change the MaxVersion of the DP_VS90DEVENV_FileSearch entry to 9.0.21022.8 (the one of the Visual Studio 2008 RTM) as depicted in the following screen capture:

image

Don't forget so save and you're done.

Please note that some features of the tools might not work with the final version of Framework 3.5, so once the updated Entity Framework and Tools are out, you should uninstall this CTP and update to the newer one!

 


I just received an update from Scott Guthrie on the Entity Framework installation issue with the RTM version of Visual Studio 2008. In a quick email to me he wrote:

I believe the team will be releasing an update shortly that works with RTM. The current build requires Beta2.

I'll keep you posted!

 


A few minutes ago I posted an article about an issue with the installer of the current ADO.NET Entity Framework version not running with the latest Visual Studio 2008 RTM.

Because I absolutely adore the Entity Framework and the work the ADO.NET team has done, I felt quite disappointed and for a few moments contemplated "downgrading" back to VS 2008 Beta 2. However, I found an easier way which involves a slight "hack" of the ADO.NET Entity Framework installer. Please note that I'm not taking any responsibility as to whether the hack works for anybody other than me or any potential side effect. Also this is very likely not a Microsoft supported hack (if there are any...).

All I can tell is that it has worked for me and for now I can use the Entity Framework with VS 2008 RTM on my machine without any issues.

Here's what I've done:

1. Locate the EFSetup-x86.exe. Use any archive software to unpack it. I used 7-Zip. This gives you the following files:

image

2. Open dp_entityframework.msi with any capable (hex) editor. I've simply used Notepad++.

3. Now search for the term "Beta2" (Note: There is NO space in front of the 2). In case you've opened the file with Notepad++ you'll find the search string in line 1155ff. If you're searching from the top, there are two hits for "Beta2" in the file which you have to skip. The third one is the one we go for. Here's how the line looks like:

code

(DP_NETFX35_INSTALLED_VERSION >= "3.5.20619.00") and (DP_NETFX35_INSTALLED_VERSION <= "3.5.20801.00")

 

4. This is where the installer checks for the existence of a specific version (range of versions) of the .NET Framework. I've carefully changed the line to the following:

code

(DP_NETFX35_INSTALLED_VERSION >= "3.5.00000.00") and (DP_NETFX35_INSTALLED_VERSION <= "3.5.90000.00")

 

So I simply replaced "3.5.20619.00" with "3.5.00000.00" and "3.5.20801.00" with "3.5.90000.00". Please note that the line breaks in the code boxes above are caused by the layout of my blog and you must not add any line breaks. Be careful to not alter the length or size of the file, simply change the numbers as described above digit by digit.

5. You're done. The installer will now seamlessly run with the RTM version of the 3.5 Framework and Visual Studio 2008 will work nicely with the Entity Framework Beta 2 drop!

 

Once a new version of the Entity Framework gets published, you should easily be able to uninstall this hacked one through the "Programs and Features" control panel application, as it gets nicely listed there:

image

Unfortunately I did not yet find a way to make it work with the Entity Framework Tools CTP 1. (UPDATE: Thanks to a reader's comment, please read this workaround!) I had these installed for the VS 2008 Beta 2 version and as far as I can tell, everything works just fine on my machine now, including the tools, which I've not been able to (re-)install. Chances are that once I've managed to install the Entity Framework itself via the hack described above, VS 2008 RTM simply picked up the DLLs which have been left behind even with me uninstalling the Entity Framework during the process of removing VS 2008 Beta 2.

 


(Update: I've been able to solve the issue via a dirty hack...)

Unfortunately the current version of the ADO.NET Entity Framework cannot be installed with the RTM version of Visual Studio 2008 released to MSDN subscribers by Microsoft yesterday. The installer gives you an "ADO.NET Entity Framework can only be installed if Microsoft .NET Framework 3.5 Beta2 is installed." error message. Obviously VS 2008 RTM ships with the RTM version of the .NET 3.5 Framework.

image 

I've sent a quick message to ScottGu - maybe he's already got an answer for us.

 


All MSDN subscribers can now down load the final RTM version of Visual Studio 2008. Most of the changes between Beta 2 and RTM address a significant performance increase (WPF designer, IntelliSense, etc.) and bug fixes. I'll update my machine tonight and will post about the experience! Stay tuned!

 

tags: , ,

Visual Studio 2008 is anticipated out early next week, with availability for MSDN Subscribers. Check out the "Top Subscriber Downloads" area on http://msdn2.microsoft.com/subscriptions for VS 2008 downloads.

You will also be able to access these downloads by clicking on the Subscriber Downloads and Product Keys links that take you to all of your downloads.

According to Microsoft they will be using two different platforms to make these downloads available - to improve discoverability and reliability, and to balance demands on the systems.

As I've got to do some exhaustive business traveling next week's first half that'll give me some late night evenings in my hotel room to update all my Beta 2 stuff to RTM!

 


Paul Andrew has posted the new Microsoft .NET Framework 3.5 Commonly Used Types and Namespaces poster. Here's the direct download link.

image

The poster follows the style of the former versions but includes this nice little illustration, depicting the Framework's additive upgrade nature, which gives developers the advantage of simplified backwards compatibility:

image

tags: , ,

I'm not a big fan of Apple (anymore). Too much vendor lock-in lately, too aggressive business habits and hardware that sucks (specifically the "I-work-for-just-three-month" never tested touch screen). So I am definitely NOT going to get an iPhone. However, while being kind of a Microsoft addict, I have to admit that I've never been happy with Windows Mobile, either.

This might change.

I might try the T-Mobile Shadow Sage. There has been a lot of talk recently as to the modified Windows Mobile which features a new user interface codenamed "Neo" and has been designed by Microsoft in collaboration with HTC and T-Mobile. Most of the available reviews focus on the new UI and I really like the idea of using a Windows based Smartphone with a slick user interface.

Here are some high-res photos captures (click for full size):

image image image

 

 


I recently started to dive into LINQ to SQL (and am actually planning to publish the first 24100.net screencast about my journey in the very near future - so stay tuned!).

In one of the projects I'm currently working on I ran into the issue of nested SQL statements and wanted to see how they translate to LINQ. We happen to have three tables

Posts - Containing blog posts with a foreign key into the Authors table
Authors - Containing author names

and

BannedAuthors, which simply contains a list of all Authors that have been banned from posting for some reason.

The query I wanted to design should retrieve all titles from all posts where the respective author is not in the BannedAuthors table. This would have been done by a nested SQL statement in traditional SQL. I ended up writing the following LINQ statement:

code

var query = from p in db.Posts
            where (
                from a in db.BannedAuthors
                select a.AuthorId
                ).Contains<int>((int)p.AuthorId) == false
            select p;

 

I was quite surprised about the straight-forwardness of this LINQ query. However, there is one immediate question which you - supposing you've done SQL stuff before - might have, too: Does this nested LINQ query mean, that we're now going to the database twice? First we get the list of banned authors from the inner statement, than we iterate through it in a foreach like approach?

Well, the answer is: No! LINQ to SQL is clever enough to figure out to translate the above statement into the following SQL query:

SELECT [t0].[Id], [t0].[Title], [t0].[AuthorId], [t0].[ViewCount]
FROM [dbo].[Posts] AS [t0]
WHERE NOT (EXISTS(
    SELECT NULL AS [EMPTY]
    FROM [dbo].[BannedAuthors] AS [t1]
    WHERE [t1].[AuthorId] = [t0].[AuthorId]
    ))

And SQL Server Profiler proves there really is just a single DB dip involved:

image

Quite cool, isn't it?

 


Microsoft released a community focused meta-data driven service repository, the Managed Services Engine (MSE) on Codeplex, Microsoft's open source project hosting site.

The Maaged Services Engine embodies an approach developed by Microsoft Services for their enterprise SOA customers.

The current 6.2 version - released as a Community Technology Preview - makes virtualization of both WCF and regular WSDL services possible and comes with a 30 minutes walkthrough.

 

 


T-Mobile is launching the Apple iPhone (of course with ridiculously expensive tariffs) and I've just recognized this:

clip_image001

For my English audience: "Egg" translated into German is "Ei" pronounced as "i".

tags: , ,

Quite silently did Microsoft release the Community Technology Preview (CTP) of the SQL Server 2005 Driver for PHP.

While Apple aggressively forces its customers into a vendor-lock situation ever since the invention of the iPod and develops more and more arrogant habits which even conflict with law, it's good to recognize that Microsoft takes its company wide vision for more transparency and openness seriously. I've tried the PHP driver and it already works pretty well. As my sites are running on the professional IIS/SQL Server stack, there's not so much real use in it for me personally, however, being able to incorporate data from my hosted SQL servers even from cheaper hosting offerings (most of them do not yet offer ASP.NET but all of them provide PHP support) is pretty nice.

I'd also like to point out the SQL Server 2005 Driver for PHP team blog which features a really nice introductory statement outlining the objectives of the new transparent engineering process at Microsoft:

 

John Bocharov, Program Manager, SQL Server Driver for PHP:

 

[...]

Transparency in the design? Over the years Microsoft has been opening up the engineering processes incrementally. Long ago there were only betas, and that was the only chance to see and give feedback about a product before it shipped. Then we started to do Community Tech Previews (CTPs). CTPs enabled us to provide bits more often and gather feedback frequently. The goal with increasing the transparency of design is to take this one step further: we would like to enable folks that are interested in our SQL Server Driver for PHP to follow the design topics as we discuss them, and have the opportunity to provide feedback right during the time where we are actively discussing a certain aspect and haven’t made a decision yet.

What exactly would we make visible? In short, our design process. To be more concrete, I’m not talking about some fancy set of specifications. What I mean is that as we go through the detailed design of the various aspects of the SQL Server Driver for PHP, we would post in this blog a) the meeting notes from our design meetings and b) deeper write-ups of specific design challenges where we’d like folks to understand how we’re seeing a problem and provide a channel for deep, detailed feedback.

How transparent is transparent? I want to be completely clear about the scope of the information we are sharing. One of the things we need to learn both from the Microsoft side and from the community side is whether the model works within a practical set of restrictions. We would post as much of our discussions as it is practically possible. However, we have to make sure we don’t compromise the interests of Microsoft as a company. There are certain things that can range from ideas to specific implementation details that we could consider trade secrets, high-value Microsoft intellectual property or something along those lines. It *will* happen that in some cases we will not discuss a topic publicly, either for a certain term (e.g. until a proper IP protection mechanism is in place) or until we ship or ever. This is nothing new, but I haven’t seen folks from large companies discuss this explicitly before, so I wanted to make sure it is clear here.

[...]

 

If you're from time to time working in PHP environments, this is definitely something you might wanna check-out!

 


With the release of all Windows Live services and applications Microsoft has added a tiny little but very powerful feature to Windows Live Messenger (formerly MSN Messenger): You now have the ability to show your status within any of your websites and - if you want - can also embed a web based version of Live Messenger to allow visitors to directly contact you.

If you're reading this post on the web (and not through a reader) you can very likely see my current status indicated in the right column just below my picture. If you chose to go to my contact page, you'll find the embedded version of Windows Live Messenger there!

Enabling this feature is pretty straight forward: Go to your web based Windows Live Messenger settings and enable anonymous status indication. As the second (and last) step create the HTML which you simply copy & paste to your site.

Note: Obviously any visitor can grab your HTML source code and indicate your status elsewhere. If you've got kind of a privacy-paranoia it might be better to not follow these instructions. ;-)

A while ago I've been playing with the Windows Live Messenger SDK and API and was quite disappointed as it's still pretty weak. I take this as a good sign that the Windows Live Messenger folks at Microsoft woke up and might create some additional great new stuff pretty soon!

By the way: The final releases of Windows Live Writer and Windows Live Mail (thick client access to all your Hotmail, Live and other mailboxes along with a great RSS reader and an ultra-fast newsgroup client) are awesome. I definitely recommend giving them a try!

 


As I am working in the (Tele)communications industry, I closely follow Microsoft's Unified Communications Platform progress. Channel 9 has just published a pretty impressive overview. I've put a to-do marker on my list to play around with OCS and specifically with its .NET extendability features!

 


Die Releases von Visual Studio 2008 und des .NET Framework 3.5 stehen vor der Tür - Grund genug einige wissenswerte Aspekte zusammenzutragen:

  • Visual Studio 2008 und das neue .NET Framework werden offiziell im Februar 2008 eingeführt, stehen aber (via MSDN) für Entwickler bereits ab November 2007 zur Verfügung. VS 2008 wird es wie gewohnt wieder in verschiedenen SKUs und Editionen geben: Vier Express Editionen (C#, VB, C++, Web) und die Standard und Professional Varianten. Die Professional Edition wird erstmals auch Unterstützung für Unit Testing beinhalten.

    Ebenfalls released werden die Team System Editionen (Architect, Developer, Test und Database) inklusive TFS und Test Load Agent. Mit Visual Studio 2008 wird mit den Bezeichnungen für diese Editionen aufgeräumt.

    Neu im Bunde ist die Visual Studio 2008 Shell, die frei verfügbar ist und analog dem Eclipse Ansatz Entwicklern eine Plattform gibt, auf denen eigene Integrierte Entwicklungsumbgebungen (IDE) implementiert werden können.

  • Das .NET Framework 3.5 stellt erneut ein additives Upgrade dar (dies war bereits beim Update auf das .NET Framework 3.0 so).

    Das heißt: Mit Fx 3.5 kommt keine neue Common Language Runtime (CLR). Das 3.0er Framework hat der Version 2.0 verschiedene Module hinzugefügt, ohne irgendeine der 2.0er Assemblies zu berühren. (Fx 3.0 stellte insbesondere WPF, WCF, WF und CardSpace zur Verfügung.) Das 3.5er Framework fügt also den 2.0 und 3.0 Assemblies zusätzliche Assemblies hinzu. Die Installation des neuen Frameworks stört vorhandene Anwendungen auf Basis der vorausgehenden Versionen in keiner Weise. (Sie ist allerdings vom Vorhandensein von Fx 2.0 SP1 und Fx 3.0 SP1 abhängig - beide Servicepacks werden zum gleichen Zeitpunkt released werden.)

  • Visual Studio 2008 unterstützt Mutlitargeting. Obwohl es parallel mit VS 2005 auf einem Rechner betrieben werden kann, ist dies nicht mehr notwendig, da man VS 2008 per Mausklick anweisen kann, für eine ältere Framework Version zu arbeiten - es stehen dann auch nur die Funktionen zur Verfügung, die von der gewählten Vorgängerversion unterstützt werden.

  • C# 3.0 und VB9 enthalten eine Fülle neuer Sprachmerkmale. Die Compiler erzeugen jedoch abwärtskompatiblen Intermediate Language Code (logisch, da es ja auch keine neue CLR gibt). In der Konsequenz bedeutet dies, dass alle neuen Sprachmerkmale in bestehenden Version 2.0 Projekten angewendet werden können! Für VB Entwickler hat sich darüber hinaus im Bereich der IntelliSense einiges getan.

  • Zu den Flagschiffen der neuen Features des 3.5er Frameworks gehört LINQ, .NET Language Integrated Query. LINQ basiert in weiten Teilen auf den neuen Sprachmerkmalen und vier neuen Assemblies. LINQ werde ich in naher Zukunft eine eigene Beitragsserie widmen.

  • Web-Entwickler erhalten mit dem neuen Release die ASP.NET AJaX Erweiterungen out-of-the-box - diese müssen also nicht mehr separat installiert werden. Zusätzlich gibt es drei neue Controls. Visual Studio 2008 wurde zusätzlich weiter verbessert und bietet nun exzellente JavaScript IntelliSense, eine neue CSS Engine und einen neuen HTML Designer, sowie Unterstützung für Nested Master Pages im Designer. Features, die alle auch problemlos für ASP.NET 2.0 Projekte genutzt werden können.

  • Entwickler für die Windows Plattform erhalten eine Fülle neuer WPF Templates und einen neuen WPF Designer, der auch die Interoperabilität von WinForms und WPF Anwendungen unterstützt. Es wird endlich auch ClickOnce und XBAP für FireFox geliefert.

  • Die Server-Entwicklung wird mit neuen WCF und WF Templates vereinfacht wobei insbesondere das Zusammenspiel beider Technologien wesentlich besser gestaltet wurde. WCF erlaubt in der neuen Version auch SOAP-less HTTP Programmierung sowie Syndication und JSON Serialisierung. Eine gute Quelle zu diesen Themen findet sich hier.

  • Last but not least kann man nur mit Visual Studio 2008 Methoden bis in den Quellcode des .NET Frameworks selbst debuggen - ein Feature für das allein genommen sich das Update bereits lohnt.

Diese Liste ist weder vollständig, noch nach dem Stellenwert der Neuerungen geordnet. Sie stellt meine persönliche Auswahl von Leistungsmerkmalen dar, die mich seit der ersten CTP bis zur aktuellen Beta 2 beschäftigt und beeindruckt haben.

Hoffentlich macht sie dem ein oder anderen Leser Lust auf mehr und erzeugt Vorfreude auf das bevorstehende Release!

 


Im ersten und zweiten Teil dieser Serie ging es um Automated Properties, Object Initializer, Collection Initializer und Extension Methods. Dieser dritte Teil widmet sich den Lambda Expressions.

Lambda Expressions gehören zu den syntaktisch anfänglich etwas weniger eingängigen neuen Sprachkonstrukten in C# 3.0. (Hinweis für VBler: In der aktuellen "Orcas" Beta stehen Lambda Expressions für VB noch nicht zur Verfügung, VB wird sie allerdings unterstützen.)

In diesem Beitrag betrachten wir lediglich die grundsätzliche Struktur von Lambda Expressions; in einem späteren Beitrag werde ich ausführlich auf Expression Trees eingehen, die eng mit dem Konzept von Lambda Expressions zusammen hängen.

Betrachten wir zum Einstieg das folgende C#-Fragment:

code

    1         delegate int SimpleDelegate(int i);
    2 
    3         static void Main(string[] args)
    4         {
    5             SimpleDelegate sd = new SimpleDelegate(SimpleMethod);
    6             Execute(sd);            
    7         }
    8 
    9         private static void Execute(SimpleDelegate d)
   10         {
   11             Console.WriteLine(d(5));
   12             Console.ReadLine();
   13         }
   14 
   15         private static int SimpleMethod (int i)
   16         {
   17             return i * 2;
   18         }

 

Bevor wir Lambda Expressions nutzen um dieses zugegeben ziemlich nutzlose Beispiel eleganter zu codieren, vereinfachen wir es zunächst durch die seit C# 2.0 zur Verfügung stehenden anonymen Methoden:

code

    1     class Program
    2     {
    3         delegate int SimpleDelegate(int i);
    4 
    5         static void Main(string[] args)
    6         {
    7             SimpleDelegate sd =
    8                 delegate(int i) { return i * 2; };
    9             Execute(sd);            
   10         }
   11 
   12         private static void Execute(SimpleDelegate d)
   13         {
   14             Console.WriteLine(d(5));
   15             Console.ReadLine();
   16         }
   17     }

 

Im Grunde haben wir eine anonyme Methode dazu verwendet, SimpleMethod() inline zu definieren (Zeile 8).

Mit einer Lambda Expression können wir den Code weiter zusammenfassen und zwar in dem wir diese Zeile

code

delegate(int i) { return i * 2; };

 


durch diese

code

(int i) => { return i * 2; };

 

ersetzen. Das delegate Keyword wurde also durch die neue Lambda Expression Syntax => ersetzt. Der eigentliche Vorteil von Lambda Expressions ist jedoch, dass man den Ausdruck weiter vereinfachen kann, insofern die Methode nur einen einzigen return Wert liefert. Gleichzeitig kann man es dem Compiler überlassen, den Parameter-Typ per Reflection zu erkennen:

 

code

SimpleDelegate sd = i=>i * 2;

 

Aus ursprünglich 8 Zeilen ist so ein Einzeiler geworden!

Es mag eingefleischten .NET Entwicklern etwas mulmig werden, ob der fehlenden Typ-Definition für i in obigem Ausdruck. Es ist jedoch wichtig zu verstehen, dass die Typsicherheit von C# nicht aufgeweicht wird, oder gar verloren geht. Der C# Compiler kann in obiger Lambda Expression den Typ von i vollständig auflösen, da der Typ des Ausdrucks i * 2 eindeutig ist. Visual Studio 2008 zeigt in logischer Konsequenz diesen natürlich auch entsprechend an:

 

image

Lambda Expressions sind nicht auf Methoden mit einem einzelnen Parameter beschränkt:

code

SimpleDelegate sd = (a, b) => a * b;

 

Übrigens: Der C# Compiler übersetzt Lambda Expressions in equivalente Delegates und Hilfsmethoden wie im Codebeispiel am Anfang dieses Beitrages, d.h. das Assemblies in denen Lambda Expressions genutzt werden, auch weiterhin auf der CLR 2.0 lauffähig sind. Lambda Expressions sind eine Spracherweiterung, keine Erweiterung der Common Language Runtime!

 


At TechEd Barcelona Microsoft announced that the next major version of Visual Studio will be released end of November 2007. Visual Studio 2008 will include the latest version (3.5) of the .NET Framework along with a ton of major productivity and feature enhancements developers across the globe have been desperately waiting for.

It is anticipated that MSDN subscribers will be the first to being able to download the RTM version of Visual Studio 2008. Check your subscription regularly!

 


Dies ist der zweite Teil meiner Serie über neue Features des bevorstehenden "Orcas" Releases von .NET - dieses mal geht es um Extension Methods.

Betrachten wir einmal das folgende Codebeispiel, welches ohne Beanstandung kompiliert werden kann:

code

    1 string name = "Ralf Rottmann";
    2 if (name.IsRalfRottmann())
    3 {
    4     Console.WriteLine("Hey there, Ralf!");
    5 }

 

Man muss schon genau hinsehen: Seit wann exportiert der .NET Typ string eine Methode bool IsRalfRottmann()?

Die richtige Antwort ist natürlich, dass dies gar nicht der Fall ist. Das Beispiel zeigt die Anwendung von Extension Methods, auch wenn es zugegeben nicht unbedingt der gängigste Use Case ist, string um eine so simple Methode zu erweitern.

Nüchtern ausgedrückt erlauben Extension Methods die Erweiterung des öffentlichen Interfaces vorhandener Common Language Runtime (CLR) Typen ohne Ableitung neuer Klassen und ohne Neukompilierung. Die .NET Language Integrated Query (LINQ) Erweiterungen basieren unter anderem auf diesem neuen Sprachmerkmal.

Der folgende Codeauszug zeigt, wie die oben dargestellte Erweiterung umgesetzt wurde:

code

    1 namespace OrcasSamples24100
    2 {
    3     public static class MyExtensionMethods
    4     {
    5         public static bool IsRalfRottmann (this string s)
    6         {
    7             return (s.Equals("Ralf Rottmann"));
    8         }
    9     }
   10 }

 

Das "Geheimnis" ist also eine statische Klasse mit einer statischen Methode IsRalfRottmann(). Der kleine aber feine Unterschied zu herkömmlichen statischen Methoden ist das this Keyword vor dem ersten Methodenparameter. Dieses teilt dem C# Compiler mit, dass die Methode den vorhandenen string Typen erweitern soll. Innerhalb der Extension Method selbst kann auf alle öffentlichen Methoden, Events und Properties der Objektinstanz zugegriffen werden, auf welche die Extension Method angewendet wird.

Um die Extension Method zu "aktivieren" muss lediglich der Namensraum importiert werden, welcher die Definition enthält. Dazu dient das bekannte using Statement:

code

    1 using OrcasSamples24100;

 

Ab sofort kann der Compiler die neue Methode für alle string Objekte auflösen. Visual Studio 2008 bietet volle IntelliSense Unterstützung für Extension Methods: