Tuesday, April 01, 2008
This is the first in what I hope will become a series on the new language features in C# 3.0 used in .NET 3.5 / Visual Studio 2008.

One thing I am not intending to cover is LINQ.  Just because the blogosphere has been buzzing with LINQ articles since the early days of "Orcas".  And with good reason I hasten to add!

Where I am starting is with the var keyword.

VB6 veterans will remember the Variant type.  A Variant could contain anything, even Object.  While this was sort of useful, my memory of it is as a synonym for:  I can't be bothered, lets just stick it in a Variant and deal with it later.

There was also a performance impact of using the special Variant type, they were large in memory and have an overhead of extra runtime checking that added up; like when assigned inside a loop for example.  They were also a special case in their un-assigned form, taking on the value Empty (test with IsEmpty()) vs Nothing (test with Is Nothing). 

So when I saw var added to C# I raised my eyebrows in the way a Fed might, when the beagle sits quietly next to your suitcase at the airport.

Most of the time you see it in the samples, it is used when returning an Anonymous Type from a LINQ query.  And this is the clue!  var is not itself a type, but instead it is a signal to the compiler to infer the type of an operation, and substitute in the required type.  It does not even have to be an Anonymous Type.  Consider the following simple example:

var result = 10 / 2.0;
Console.WriteLine(result.ToString());

By the time this code is compiled, var is replaced with double.  In fact, the Intellisense on result will be correct for it being a double.

To confirm this, looking at those lines of the assembly in Lutz Roder's Reflector show the following after disassembly:

double result = 5.0;
Console.WriteLine(result.ToString());


OK, so var can be used independant of Anonymous Types, but why would you want to be less explicit in typing your variables?  Consider the following fictitious example:

DatabaseRequestService req = DatabaseRequestService.CreateFrom(value);

And compare it with the equivalent line using var:

var req = DatabaseRequestService.CreateFrom(value);

Here, var leads itself to much more readable syntax with the same typing, Intellisense, and everything else!

Listening To:  Róisín Murphy

Tuesday, April 01, 2008 9:25:00 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, August 15, 2007

For a limited time, members of CSharpZealot.com have access to some free Silverlight training content!  Here's how:
Easy!

Also, I'm impressed at how well the InnerWorkings bits integrate with Visual Studio during the training experience.  You should really check it out.

Now please keep in mind that Web 2.0 (and it's previous incarnation, Web 0.9) supports bi-directional time travel
  • Forward, at a pace of 1 second per second, same as daily life, really; and
  • Backwards at a rate of 20 yrs in, say, about 150 miliseconds.
That means that if you are reading this blog post some time in the future, this offer may be closed.  It's only open for a limited time, so get to it!  Don't be the last guy on the block to not know how to use the MediaElement and VideoBrush in Silverlight!

Mad props (that's what the kids say these days, don't ya know?) to Brian Madsen, btw, for keeping CSharpZealot the place to get your .NET love.

Wednesday, August 15, 2007 6:01:21 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, July 03, 2007
It became clear to me during my last blog post on the .NET landscape that it was going to grow into more than one post. 

Framework Versions

One fact that is important to note about the graphic in that post, and it was the catalyst for me making the drawing, is that the .NET 3.0 and .NET 3.5 frameworks do not supersede .NET 2.0 but augment it.

What I mean by this is if you were to look into your %WINDIR%\Microsoft.NET\Framework\v3.0 folder you do not get a new System.Data.Dll or System.Web.dll.  Instead you see the folders for:
If you look in your %WINDIR%\Microsoft.NET\Framework\v3.5.xxx\ (still beta at time of writing) the main thing to note here is a new csc.exe and vbc.exe.

So what do you get with .NET 3.5 & Visual Studio 2008 (codename "Orcas")?

Update:  Please also check out Daniel Moth's whole bunch Orcas posts, and his run-down of the new bits.

...and last but not least, the golden haired child, LINQ...

...and for everything that I have missed, or is not in the beta bits yet, grab the Orcas overview whitepaper.

What is .NET 3.5 going to do to 3.0?

It seems it has to do with Green Bits and Red Bits (source: Daniel Moth).  In other words, .NET 3.5 will also include SP1 for .NET 3.0 and SP1 for .NET 2.0.

Tuesday, July 03, 2007 9:11:18 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
 Sunday, July 01, 2007
When I started playing with LINQ, I needed to get some clarity on this in my mind, so in the spirit of Linnaeus, Mendeleev and Gell-Mann, I put together a graphic that showed the generations of the various bits, and after talking with friends thought it was worth sharing:

UpdateDaniel Moth has a better graphic for the same data on his blog first.  Shame, not an image map. :-)

Mohammad Adil Akif also has a version in his blog.

...This is the blog version - the original form was a Post-It note.
...And in the spirit of Web 0.9 (which came before Web 2.0 :-) the graphic is an image map :-)

I know there is much more coming, like the Dynamic Language Runtime, Domain-Specific Language tools, Silverlight, and so on.   I've also chosen not to call out the versions of Team System, both in the interest of clarity.
Sunday, July 01, 2007 11:51:05 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [1]  | 
 Tuesday, May 29, 2007

I've just got a couple of lessons from the last week to share around developing Office 2003 (and specifically Visio 2003) Add-Ins

I'm also trying to saturate this post with links because I have come up with a good size folder in my bookmarks for what started out to be a simple task.

  • Grab the PIA'sAnyone who wants to run the Add-In will need them.  Alternatively they can be installed from the Office Add/Remove/Repair under the guise of .NET Programmability Support, but in reality the user may not have the media or security access to do this.  Do NOT however ship the PIA's in your bits.  Ship the PIA's with your bits:  This means 2x MSI's.
  • Using NAant to automate the build with csc.exe & vbc.exe is suboptimal.  I'm keeping my project to one small assembly that depends on the PIAs, and also depends on another assembly that does the heavy lifting but has no ref to the PIA's.
  • Strong Name everything.  Well, strong name everything anyway, but when trying to pass of managed code as COM it is essential.
  • You cannot load a .NET DLL, even one with the ComVisibleAttribute on the Assembly or Classes, via the Office UI.  You just can't.  KB316723 gives an explanation.  This is because Office will try and register it the old regsvr32 way, which of course won't work.  To get a .NET DLL into the Macros -> Add-Ins list, you must write the registry entry under: HKEY_CURRENT_USER\Software\Microsoft\<office program name>\Addins\
  • This brings me to my next point.  KB316723 hints at it, but your setup must write a HKCU key not a HKLM key.  The Shared Add-In Wizard in Studio is ambiguous when it shows you this choice:

  • I know this may be contentious, but consider using VB.NET over C#.  This depends of course, but some parts of the Office object model make heavy use of Optional Parameters which C# does not support.  It has been noted elsewhere what Type.Missing can do for readability.  Having said that, it does vary greatly depending on where in the Office Object Model you are.
  • Spend some time with the Setup project that the Shared Add-In Wizard makes and test it.  Once you like it, reverse engineer it to a WiX script and feed that to your automated build.  For the record, you do that with:

Dark.exe –x path Debug/msi My.wxs
Candle My.wxs
Light My.Wixobj

  • To extra points when dealing with WiX-ified MSI's
    1. It's useful to note that the extracted (-x) resources take many forms.  DefBannerBitmap.ibd for example is just a bitmap.  I think it is easier to rename it to .bmp & tweak it in Photoshop than to add a new banner in Visual Studio.
    2. The Add-in reg setting mentioned in point #4 above references an assembly version.  Visual Studio tweeks this for you but your WiX script will be frozen at the time your Dark.exe'd it.  So don't auto-increment your assembly version numbers, or tweak you WiX script.  The choice is yours but your MSI must write the version of the Add-In DLL to the target machine's registry.

Listening To: Leftfield, Leftism

Tuesday, May 29, 2007 12:53:56 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
 Monday, March 26, 2007

So I feel that my last post on pretty gray info bars in Photoshop could do with a second chapter :)

This is a pretty long series so I'll be breif - what follows is the rough outline of how to achieve the same result as a User Control in your Visual Studio project.  The advantage of this aproach would be to allow you to dymanically add text or other sparkle of your own creation :-)

Here's a sample:

Code follows :-)

namespace GrayBar
{
   public partial class GrayBar : UserControl
   {
      public enum GrayBarModes
      {
         GreenTick = 0,
         YellowBang = 1,
         RedX = 2
      }

      public GrayBar()
      {
         InitializeComponent();
      }

      protected override void OnPaint(PaintEventArgs e)
      {
         Graphics g = this.CreateGraphics();
         g.SmoothingMode = SmoothingMode.HighQuality;

         // Fill the whole canvas
         Rectangle wholeControlSpace = new Rectangle(0, 0, this.Width, this.Height);
         Brush controlFiller = new LinearGradientBrush(wholeControlSpace, Color.DarkGray, Color.LightGray, LinearGradientMode.Vertical);
         g.FillRectangle(controlFiller, wholeControlSpace);

         // Make icon in corner
         Rectangle iconSpace = new Rectangle(1, 1, this.Height - 2, this.Height - 2);
         Brush iconFiller = new LinearGradientBrush(iconSpace, Color.Gray, Color.DarkGray, LinearGradientMode.Vertical);
         g.FillEllipse(iconFiller, iconSpace);
         base.OnPaint(e);

         Font iconFont = new Font(FontFamily.GenericSansSerif, 12, FontStyle.Regular);
         string iconText = "";
         Brush iconTextBrush = new SolidBrush(Color.NavajoWhite);

         float fontHight = this.Height; 

         // The Font, Text and Colour depends on the setting on our GrayBarMode property
         switch (GrayBarMode)
         {
            case GrayBarModes.GreenTick:
               iconFont = new Font("Wingdings 2", fontHight, GraphicsUnit.Pixel);
               iconText = "P"; // P == "tick" in "Wingdings 2"
               iconTextBrush = new LinearGradientBrush(iconSpace, Color.DarkGreen, Color.LightGreen, LinearGradientMode.Vertical);
               break;
            case GrayBarModes.YellowBang:
               iconFont = new Font("Arial", fontHight, FontStyle.Bold, GraphicsUnit.Pixel);
               iconText = "!"
               iconTextBrush = new LinearGradientBrush(iconSpace, Color.Orange, Color.Yellow, LinearGradientMode.Vertical);
               break;
            case GrayBarModes.RedX:
               iconFont = new Font("Arial", fontHight, FontStyle.Bold, GraphicsUnit.Pixel);
               iconText = "X"
               iconTextBrush = new LinearGradientBrush(iconSpace, Color.Maroon, Color.Red, LinearGradientMode.Vertical);
               break;
            default:
               throw new ApplicationException("Unknow Mode");
         }

         float iconTextXPos = (iconSpace.Width / 2) - (iconFont.GetHeight(g) / 4);
         float iconTextYPos = (iconSpace.Height / 2) - (iconFont.GetHeight(g) / 2);
         g.DrawString(iconText, iconFont, iconTextBrush, iconTextXPos, iconTextYPos);

      }

      private GrayBarModes _GrayBarMode = GrayBarModes.GreenTick;
      public GrayBarModes GrayBarMode
      {
         get
         {
            return _GrayBarMode;
         }
         set
         {
            _GrayBarMode = value;
         }
      }

      private string _MessageText;
      public string MessageText
      {
         get
         {
            return _MessageText;
         }
         set
         {
            _MessageText = value;
         }
      }

   }
}

C# | Geeking Out! | UX
Monday, March 26, 2007 9:26:02 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
 Friday, March 16, 2007
...snipped from a discussion earlier today with someone who should know about C#!

btw, I found one conclusive reason as why to use C# over VB.Net when doing unit tests with NMock
in C# the line is:

Expect.Once.On(mockFetcher).Method("GetDatabases").Will(Return.Value(mockReturnValue));

in VB it is:

Expect.Once.On(mockFetcher).Method("GetDatabases").Will(NMock2.Return.Value(mockReturnValue))

Return is a NMock2 type as well as (with caps) a VB reserved word!  so you have to add a qualifier.

taking into consideration the semicolon that's 6 extra keystrokes!

Friday, March 16, 2007 4:23:05 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, February 27, 2007

Just a follow-up on my post of yesterday about the intent of exposing a read-write property of an Array/Collection type.

Practical Guidelines and Best Practices has the following guidance (i'm paraphrasing)

13.13 To protect the state of a backing var for properties that return arrays, consider

get { return DirectCast(_arr.Clone(), string()); }

which is good protection, but less efficient.  Or, provide indexed access to the array by an indexed property or function.  Getting close...

13.14 Properties that return a collection should be read-only to prevent clients replacing the whole array with a new one, or with a null reference as that could break assumptions elsewhere in the class. Disco! 

Thanks lads!

Tuesday, February 27, 2007 7:53:36 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
 Monday, February 26, 2007

This one came up in discussion last week and could be worth mentioning.

Consider the following property:

private List<SchemaAttribute> _attributes = new List<SchemaAttribute>();
public List<SchemaAttribute> Attributes
{
   get
   {
      return _attributes;
   }
   set
   {
      _attributes = value;
   }
}

NCover/NCoverExplorer reliably inform me that this property has only 50% coverage
in my tests.

By hereto unexplored forces of nature, every consumer of this class calls
.Attributes.Add()

or, itterates over it as so:
foreach (SchemaAttribute element in instance.Attributes)
{
   // ...
}

The keen eye will notice that neither of these ways to access the property actually hit the setter! 

Two possible paths present themselves:

  1. Write a test that just exercises the setter.  This seems to me pointless. 
    If we are to consider that our tests can serve to express our intention
    in a repeatable fashion, what is our intent?  To see if a Generic List still works?
  2. Consider makeing the property read-only.  Including braces I could own three lines less code.  Yay!
    And also now I have had cause to think about it, it's not my intention that the
    List be set as a list, for this class it just dosen't make sense right now.

Next step?  Consult Francesco & Giuseppe!

Sleep.  The best 10 hours of the week.

Listening to:  Nick Cave and the Bad Seeds - Abattoir Blues

Monday, February 26, 2007 1:02:40 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  |