Wednesday, October 29, 2008

Comprehension vs lambda queries



It's a very much debated argument like C# vs VB.NET lambda or comprehension queries (LINQ). Personally I prefer LINQ comprehension queries purely because they seem less functional and more imperative and to me they are easier to read.

C#, or VB if you prefer, support both.

Take the following simple LINQ query:
static void Main(string[] args)
{
string[] cities = { "London", "Paris", "New York" };
Console.WriteLine((from c in cities where c.Contains('L') select c).First());
}
Note we are still using extensions methods in the LINQ query. Now consider the lambda version:
static void Main(string[] args)
{
string[] cities = { "London", "Paris", "New York" };
Console.WriteLine(cities.Where(c => c.Contains("L")).First());
}
For me I prefer the LINQ version easier to read.

If we inspect the IL we will see identical generated code. First is the LINQ IL:
        
L_0023: ldsfld class [System.Core]System.Func`2 ConsoleApplication6.Program::CS$<>9__CachedAnonymousMethodDelegate1
L_0028: brtrue.s L_003d
L_002a: ldnull
L_002b: ldftn bool ConsoleApplication6.Program::
b__0(string)
L_0031: newobj instance void [System.Core]System.Func`2::.ctor(object, native int)
L_0036: stsfld class [System.Core]System.Func`2 ConsoleApplication6.Program::CS$<>9__CachedAnonymousMethodDelegate1
L_003b: br.s L_003d
L_003d: ldsfld class [System.Core]System.Func`2 ConsoleApplication6.Program::CS$<>9__CachedAnonymousMethodDelegate1
L_0042: call class [mscorlib]System.Collections.Generic.IEnumerable`1 [System.Core]System.Linq.Enumerable::Where(class [mscorlib]System.Collections.Generic.IEnumerable`1, class [System.Core]System.Func`2)
L_0047: call !!0 [System.Core]System.Linq.Enumerable::First(class [mscorlib]System.Collections.Generic.IEnumerable`1)
L_004c: call void [mscorlib]System.Console::WriteLine(string)
L_0051: nop
L_0052: ret
.method private hidebysig static bool 
b__0(string c) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()
.maxstack 2
.locals init (
[0] bool CS$1$0000)
L_0000: ldarg.0
L_0001: ldc.i4.s 0x4c
L_0003: call bool [System.Core]System.Linq.Enumerable::Contains(class [mscorlib]System.Collections.Generic.IEnumerable`1, !!0)
L_0008: stloc.0
L_0009: br.s L_000b
L_000b: ldloc.0
L_000c: ret
}
.field private static class [System.Core]System.Func`2 CS$<>9__CachedAnonymousMethodDelegate1
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()
}
Now we have the lambda IL:
L_0023: ldsfld class [System.Core]System.Func`2 ConsoleApplication6.Program::CS$<>9__CachedAnonymousMethodDelegate1
L_0028: brtrue.s L_003d
L_002a: ldnull
L_002b: ldftn bool ConsoleApplication6.Program::
b__0(string)
L_0031: newobj instance void [System.Core]System.Func`2::.ctor(object, native int)
L_0036: stsfld class [System.Core]System.Func`2 ConsoleApplication6.Program::CS$<>9__CachedAnonymousMethodDelegate1
L_003b: br.s L_003d
L_003d: ldsfld class [System.Core]System.Func`2 ConsoleApplication6.Program::CS$<>9__CachedAnonymousMethodDelegate1
L_0042: call class [mscorlib]System.Collections.Generic.IEnumerable`1 [System.Core]System.Linq.Enumerable::Where(class [mscorlib]System.Collections.Generic.IEnumerable`1, class [System.Core]System.Func`2)
L_0047: call !!0 [System.Core]System.Linq.Enumerable::First(class [mscorlib]System.Collections.Generic.IEnumerable`1)
L_004c: call void [mscorlib]System.Console::WriteLine(string)
L_0051: nop
L_0052: ret
method private hidebysig static bool 
b__0(string c) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()
.maxstack 2
.locals init (
[0] bool CS$1$0000)
L_0000: ldarg.0
L_0001: ldstr "L"
L_0006: callvirt instance bool [mscorlib]System.String::Contains(string)
L_000b: stloc.0
L_000c: br.s L_000e
L_000e: ldloc.0
L_000f: ret
}
.field private static class [System.Core]System.Func`2 CS$<>9__CachedAnonymousMethodDelegate1
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()
}
As you can see the code is almost identical. The only difference is in the calling of the Contains method. With LINQ we are calling Contains on IEnumerable whereas with lambda Contains is on the string class. You can see this in the IL b__0 method.

So it's really about personal choice.

Compact Framework v.next

As you have probably heard by now. Visual Studio 2010 and the .NET Framework v4.0 CTP was announced and released at PDC and can be downloaded here: http://www.microsoft.com/downloads/details.aspx?FamilyID=922b4655-93d0-4476-bda4-94cf5f8d4814&DisplayLang=en#filelist

If you're expecting the next version of the Compact Framework to be included in this CTP you'll be dissapointed. CF v.next didn't make this CTP.

The CTP comes as a virtual machine on Windows Server 2008 which also includes TFS CTP 2010.


Monday, October 27, 2008

Inversion of Control Pattern MSDN article

I read a very well written article this month on the Inversion of Control (separation of concerns) pattern by Jeremy Miller. I think it's worth a read here: http://msdn.microsoft.com/en-us/magazine/cc947917.aspx

Sunday, October 26, 2008

LINQPad

A new tool I learned about recently from Eric Nelson called LINQPad. It is a tool that allows you to write LINQ queries directly into its IDE then execute them.

There is support for:

-LINQ to SQL
-LINQ to Xml
-LINQ to Objects

You can of course see the results and also the SQL generated (DLINQ) - which saves you the need to troll through the SQL Profiler when performance tuning your code.

In addition the guy who wrote this tool also wrote a book called C# in a Nutshell. All the code examples in his book can be found in this tool which you can change and execute if you want. A great way to learn LINQ.

It supports VB too. There is no support for LINQ to ADO.NET (Entities) so you won't get to see the SQL generated. Other than that the LINQ will be the same.

Get it here.

Thursday, October 23, 2008

Getting Started with C#

Rob Miles has kindly published (for free) a book that he uses as a basis of the first year programming course at the University of Hull.

Get the book from here.

Sunday, October 19, 2008

The next MSDN Windows Mobile App Developer Chat

The next Windows Mobile Application Developer Chat is on November 11th 10:00 - 11:00 Pacific time.

Synopsis:
Do you have questions regarding Windows Mobile application development that you need answers to? Spend an hour with Microsoft employees and MVPs who are experts in Windows Mobile application development. Please join us for a live chat and bring on the questions! This chat will cover the tools and technologies used to develop applications using the Windows Mobile operating system.

Add this event to your calendar here.

Enter the chat here.

Why the iPhone 3G is rubbish!



Well I bought an iPhone 3G around 1 month ago so I have 1 month experience of using it so I think I have a good idea of it's capabilities.

First lets start with the positives.

The things I like about the iPhone:-

  1. Web browser. This is probably one the best parts of the device. It is usually quick and the zoom features and rendering engine are quite good.
  2. The phone. Of course a big part of the iPhone is the phone, is it any good? Yes very much probably the best phone experience I've had with any phone (although don't upgrade to v2.1 as since I've done this the phone just hangs up randomly while talking to people even though I have full signal)
  3. iPod built-in. The iPod is good. Apple doesn't have that stupid circular "wheel" to control the volume. There is a separate button for this.


The things I don't like about the iPhone:

  1. Web browser. I know I put the web browser as one of the good things about the iPhone but there is no support for Flash/Flash Lite or Silverlight and Apple (currently) don't intend to support either of these in the future.
  2. No support for forwarding SMS??!!??
  3. No support for MMS.
  4. No way to save attachments to the device via emails.
  5. No voice recording.
  6. No video recording support for the camera.
  7. Camera is only 2mp.
  8. GPS chipset sucks (even though it is SiRFIII, which is proven and works great in other devices). When you do get a satellite lock it only lasts for a couple of minutes then its gone again and I've tried this in various locations here in the UK and abroad. I have many GPS devices, phones, receivers and they all work once locked on. My older external GPS receivers maintain a lock-on while the iPhone loses it's lock.
  9. No sat nav software. Even if the GPS worked, what good is it without any kind of satellite navigation software for road users. You can use the Google maps application built-in that comes with the iPhone but it is certainly no match for software such as TomTom. In addition Google maps require the maps to be downloaded (tiles) on the fly, so if you have no radio, you lose you're way!
  10. iTunes - rubbish - I know iTunes is not part of the iPhone, but I could devote an entire blog post on its short comings
  11. Synchronization with Outlook. No support for notes. The iPhone has its own notes store, which has no relationship with outlook.
  12. It is also not possible to sync with an address book that happens to belong on exchange server in addition no support with syncing with offline emails that are part of an exchange server. However it is possible to sync with an exchange server OTA although I could never get this to work with my exchange server which is hosted with external access over HTTP.
  13. Images in emails are downloaded automatically, there is no configuration to turn this off.
  14. Long URLs are truncated in mail making them appear friendly when they might not be. The register has an article on this here: http://www.theregister.co.uk/2008/10/06/unfixed_iphone_vulns/
  15. Only a max of 200 emails can be downloaded to the device until you scroll all the way to the bottom of the list then request another block (I think something like 10 or so). So even though I have 8GB of space it is a painful task to get my entire mailbox downloaded to the phone. Rubbish.
  16. There is no search facility in the mail program. I can't even filter by date or person so finding emails is a task in itself.
  17. The accelerometer (automatic adjusting of the screen in portrait or landscape depending which way up the device is) is ok for some features of the phone such as viewing pictures but when using the iPod software for listening to music I find it very irritating as when the screen is in landscape mode you lose pretty much all the features such as controlling the volume, skipping the track etc. Turning the device back to portrait is the only solution which is minor but just irritating. There is no configuration to turn this off.
  18. Connectivity. As I travel a lot I go from areas where EDGE, 3G are not available so when I previously had a connection, maybe 3G, reconnecting via a different protocol such as GPRS in this case just doesn't work very well. Getting emails and browsing the Internet takes forever and it is quicker to turn the device off then back on again.
  19. Contacts, why can I not search by contact name???? You can tap the letter of the persons name (small A-Z listed on the right hand side of the list) and focus to navigate to that area of the list. The contacts list pretty much always locks up for a brief moment on load which is irritating. Upgrading to 2.1 doesn't fix this.
  20. Email. There are options which allow you to configure the device to poll a pop3 server periodically - which is fine the smallest unit is 15 minutes. But it just doesn't work. You have to load up mail and hit 'request mail'. And why can't I set the device to poll my pop3 server every 1 minute I have an unlimited data plan.
  21. Locking the device. What is this all about. Every time you turn the device on you have to slide this button from one side of the screen to another. This is fine, but why can't I turn it off?
  22. I know the iPhone is a touch device, but why is there no hard button for hanging up or answering. It would be good to have these hard buttons in addition to the on screen touch ones - just a minor irritation.
  23. Security hold which allows you to bypass the PIN security number and gain access to features of the phone. See here: http://blog.wired.com/gadgets/2008/08/massive-iphone.html
  24. Jason Langridge shows a comparison of push email between WM and iPhone here: http://blogs.msdn.com/jasonlan/archive/2008/07/18/iphone-2-0-windows-mobile-for-push-email.aspx
  25. No copy and paste functionality.
  26. The OS is single-task based, so coming from a multitalking desktop environment to the iPhone platform is painful.

There you have it, my comprehensive list. I have since retired the iPhone from my arsenal of devices. Maybe the iPhone will be a major player in future versions, we'll have to wait and see.

Setting the name of a Windows Mobile device programmatically

Setting the name of a Windows Mobile powered device can be achieved by manipulating the registry. Since CF 2.0 we have had the luxury of a Registry managed wrapper, so there is no need to P/Invoke the registry API.

This post shows a simple example how to read and update the name of the device - which is stored in the registry.

I've written a simple bit of code that looks like the following:
using Microsoft.Win32;
public partial class Form1 : Form
{
private const string IDENTITY = @"HKEY_LOCAL_MACHINE\Ident";
private const string NAME = "Name";
public Form1()
{
InitializeComponent();

}

private void apply_Click(object sender, EventArgs e)
{
Registry.SetValue(IDENTITY, NAME, deviceName.Text);
}

private void Form1_Load(object sender, EventArgs e)
{
deviceName.Text = (string)Registry.GetValue(IDENTITY, NAME, "NAME");
}
}
The form looks like the following:


Mobile app pre-change

This can also been seen from the Settings\System\About\Device ID applet:


Device name pre-change

Also this can be seen via the Windows CE Remote Registry Editor (CE Remote Tools):



Now we simply change the "MyDevice" to "NewDeviceName" and click the Apply button. Our change is propagated instantly if we go and check the settings applet again:



It's as simple as that!

Thursday, October 02, 2008

Passing data from a Microsoft CRM custom form to an IFrame web app running under Microsoft CRM 4.0

Sounds simple doesn’t it? Well it is kind of, but finding the solution was a bit of a pain…

As you probably know CRM customizations support IFrames – which are the only way to have true integration in the CRM UI (as per the current latest version which is 4.0). The “only way”, at least, the way I have figured to do this – is to pass this data across via the querystring, that is, append it to the URL.

You can do this using (unfortunately) JavaScript. You override the OnLoad event for the CRM form in customizations (form properties) and the code looks something like the following:
var myData=crmForm.all.crm_field.DataValue;
//Append the variable to the aspx page.
var URL=crmForm.all.IFRAME_crm_my_form.src;
// pass the URL to the IFRAME
crmForm.all.IFRAME_crm_my_form.src=URL + '&querystring=' + myData;
I need to explain the above script a bit.

crm_field is a type that belongs to the entity. This might be a custom entity or a CRM one, it doesn’t matter.
IFRAME_crm_my_form is the schema name for the custom IFrame (ASPX page). We simply get the current URL so that we can append the querystring.

I'd be interested in hearing any other ways of solving this problem...