A world apart from the everday ...

Assert.IsTrue(Entries.Count == 0);

April 2005 - Posts

Follow up post on ... Where oh where is my with statement ...

seems like our friendly folk over at Redmon have been reading my blog :)

no just kidding but i found this post on the “Ask a language designer” forum which i thought was just too uncanny!

go check it out ... Seems our local boys were on the right track as to why there is no such statement in C#, well done guys ...\

http://msdn.microsoft.com/vcsharp/team/language/ask/withstatement/default.aspx

 

well that puts that issue to rest ...

happy coding without the with statement.

Cheers

Posted: Apr 14 2005, 07:56 PM by Ryan CrawCour | with 3 comment(s)
Filed under:
Where oh where is my "With...EndWith" statement?
ok this one might take some time to read so i apologise upfront; but i just had to get this off my chest ....
 
I do so miss the With ... End With strucutre that good old VB6 and VB.NET offers.
Why i hear you gasp in angst ... well for two reasons ...
 
1. I am LAZY !
instead of typing;
    int a = object.PropertyA;
    int b = object.PropertyB;
    ...
    int z = object.PropertyZ;
 
using “With .. End With” i could simply type the following;
  with object
    int a = .PropertyA;
    int b = .PropertyB;
    ...
    int z = .PropertyZ;
 end with
 
so by my rudementary math skill that saves me typing a lot of characters each time i want to use a property on the object.
ok not a compelling enough reason for you, how about this one then ...
 
2. With ... End With improves performance.
 
before all you C# purists out there choke and die or something, hear me out ...
 
Let's look at a classic example of accessing the rows collection in the DataTable class under a DataSet class:
 
ds.Tables("yada").rows
 
This generates the following;
 
callvirt   instance class [System.Data]System.Data.DataTableCollection
             [System.Data]System.Data.DataSet::get_Tables()
 
ldstr      "yada"
 
callvirt   instance class [System.Data]System.Data.DataTable
             [System.Data]System.Data.DataTableCollection::get_Item(string)
 
callvirt   instance class [System.Data]System.Data.DataRowCollection
             [System.Data]System.Data.DataTable::get_Rows()
 
So accessing the rows collection in a data table object results in 3 calls to 3 property getters "get methods".
What happens if we do 3 accesses to the rows collection, will there be 9 calls to "get methods" generated?
Take a look at this code example:
 
ret = ds.Tables["yada"].Rows.Count;
if(ds.Tables["yada"].Rows.IsReadOnly) {}
ds.Tables["yada"].Rows.Clear();
 
simple calls to 3 different properties on the rows collection, but is it ...
what happens in the generated IL code?
 
ldloc.0
callvirt   instance class [System.Data]System.Data.DataTableCollection
             [System.Data]System.Data.DataSet::get_Tables()
ldstr      "yada"
callvirt   instance class [System.Data]System.Data.DataTable
             [System.Data]System.Data.DataTableCollection::get_Item(string)
callvirt   instance class [System.Data]System.Data.DataRowCollection
             [System.Data]System.Data.DataTable::get_Rows()
callvirt   instance int32 [System.Data]System.Data.InternalDataCollectionBase::get_Count()
stloc.1
 
ldloc.0
callvirt   instance class [System.Data]System.Data.DataTableCollection
             [System.Data]System.Data.DataSet::get_Tables()
ldstr      "yada"
callvirt   instance class [System.Data]System.Data.DataTable
             [System.Data]System.Data.DataTableCollection::get_Item(string)
callvirt   instance class [System.Data]System.Data.DataRowCollection
             [System.Data]System.Data.DataTable::get_Rows()
callvirt   instance bool [System.Data]System.Data.InternalDataCollectionBase::get_IsReadOnly()
brfalse.s  IL_0066
 
ldloc.0
callvirt   instance class [System.Data]System.Data.DataTableCollection
             [System.Data]System.Data.DataSet::get_Tables()
ldstr      "yada"
callvirt   instance class [System.Data]System.Data.DataTable
             [System.Data]System.Data.DataTableCollection::get_Item(string)
callvirt   instance class [System.Data]System.Data.DataRowCollection
             [System.Data]System.Data.DataTable::get_Rows()
callvirt   instance void [System.Data]System.Data.DataRowCollection::Clear()
 
it actually calls the same methods 3 times.
What we want to do is to make sure that the "get methods" only get called once for all the access to the rows collection.
If we were in VB.NET this would be simple by using the with...end with statement.
 
  With ds.Tables["yada"].Rows
      Ret = .Count
      If .IsReadOnly
      End if
      .Clear
  End With
 
This creates an extra object in the methods local area, used by the IL code when executing.
 
.locals init ([0] class [System.Data]System.Data.DataSet ds,
          [1] int32 i,
          [2] class [System.Data]System.Data.DataRowCollection _Vb_t_ref_0)
 
The last local variable ([2]), is generated at compile time when the compiler finds the with statement in the VB.Net code.
The IL code now takes advantage of this extra local variable by passing the reference to the rows collection to that extra hidden variable in the locals.
 
ldloc.0
callvirt   instance class [System.Data]System.Data.DataTableCollection
             [System.Data]System.Data.DataSet::get_Tables()
ldstr      "yada"
callvirt   instance class [System.Data]System.Data.DataTable
             [System.Data]System.Data.DataTableCollection::get_Item(string)
callvirt   instance class [System.Data]System.Data.DataRowCollection
             [System.Data]System.Data.DataTable::get_Rows()
stloc.2
 
When this has been done, instead of calling all the get methods, there will now be calls directly to the hidden variable
 
ldloc.2
callvirt   instance int32 [System.Data]System.Data.InternalDataCollectionBase::get_Count()
stloc.1
ldloc.2
callvirt   instance void [System.Data]System.Data.DataRowCollection::Clear()
nop
ldloc.2
callvirt   instance bool [System.Data]System.Data.InternalDataCollectionBase::get_IsReadOnly()
brfalse.s  IL_0044
nop
 
This IL code looks much better and has fewer method calls.
FYI, if you look at the IL code the "End With" statement generates you will see it even cleans up after itself
 
ldnull
stloc.2
 
Now the kind folks at C# decided not to give use this little beauty because they though us "real" programmers had no need for this ...
Here's a proposal to try mimic the behaviour:
 
DataRowCollection drc = ds.Tables["yada"].Rows;
ret = drc.Count;
if(drc.IsReadOnly) {}
drc.Clear();
drc = null;
 
Not really as nice looking in Visual Studios as the VB.NET equivalent, but this will do the exact same thing as the VB.NET with...end with statement.
 
But this was about performance i hear you complaining, not about how nice something looks that we don't really care about ... fair point;
so let's take a look at that now;
below is a simple performance test comparing the first and the last C# code examples.
 
    class Class1
    {
        [STAThread]
        static void Main(string[] args)
        {
             DoWork(10000);
             DoWork(100000);
             DoWork(1000000);
             Console.ReadLine();
        }
 
        private static void DoWork(int iterations)
        {
            foo obj = new foo();
            long deltaticks = 0;
               
            // first way, without our "with...endwith" mimic.
            Console.WriteLine("Executing using the properties");
            deltaticks = obj.barslow(iterations);
            Console.WriteLine("Time to execute " + iterations.ToString() + " times:" + deltaticks.ToString() + " ticks");
   
            // second way, using our "with...endwith"
            Console.WriteLine("Exectuing through an object");
            deltaticks = obj.barfast(iterations);
            Console.WriteLine("Time to execute " + iterations.ToString() + " times:" + deltaticks.ToString() + " ticks");
        }
    }
   
    public class foo
    {
        public long barfast(int iterations)
        {
            DataSet ds = new DataSet();
   
            int ret = 0;
            long startticks = 0;
            long deltaticks = 0;
   
            ds.Tables.Add("yada");
   
            startticks = System.DateTime.Now.Ticks;
 
            DataRowCollection drc = ds.Tables["yada"].Rows;  
            for(int ix = 0;ix < iterations;ix++)
            {
                ret = drc.Count;
                if(drc.IsReadOnly) {}
                drc.Clear();
            }
   
            drc = null;
            deltaticks = System.DateTime.Now.Ticks - startticks;
            return deltaticks;
        }
 
        public long barslow(int iterations)
        {
            DataSet ds = new DataSet();
  
            int ret = 0;
            long startticks = 0;
            long deltaticks = 0;
  
            ds.Tables.Add("yada");
  
            startticks = System.DateTime.Now.Ticks;  
  
            DataRowCollection drc = ds.Tables["yada"].Rows; //just to have the same overhead as the method above, but this is not used
            for(int i = 0; i < iterations; i++)
            {
                ret = ds.Tables["yada"].Rows.Count;
                if(ds.Tables["yada"].Rows.IsReadOnly) {}
                ds.Tables["yada"].Rows.Clear();
            }
 
            deltaticks = System.DateTime.Now.Ticks - startticks;
            return deltaticks;
        }
    }
 
The result from the test is shown in table 1,
 
Iterations  | Through properties         | Through object         | Difference
10000      | 312568                          | 156284                    | 200%
100000    | 1875408                        | 781420                    | 240%
1000000  | 19535500                      | 8751904                  | 223%
 

Note that these figures are approx but it's fair to say that the difference averages around 220-260%.
 
so in summary;
i plead with Anders Hejlsberg to give us C# developers a proper "with..endwith" statement for the sake of my laziness, but more importantly for the laziness of my poor pc's processor!
Posted: Apr 07 2005, 04:50 PM by Ryan CrawCour | with 8 comment(s)
Filed under:
System.Web.Mail, OH MY!
so who has tried to send an email using .NET yet?
easy you say ... well in theory it should be ... that is until you get the wonderful  “Could not access 'CDO.Message' Object” error!
i mean how useful is this message?
 
the CDO objects are there ao why can't they be accessed!?!
 
in fact dig a little deeper my dearest plebbs and discover another intricate little “un-documented feature” ... the real exception is hidden about 5 levels deep!
 
"System.Web.HttpException: Could not access 'CDO.Message' object. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Runtime.InteropServices.COMException (0x8004020F): The server rejected one or more recipient addresses. The server response was: 553 malformed address: \r\n\r\n --- End of inner exception stack trace ---\r\n at System.RuntimeType.InvokeDispMethod(String name, BindingFlags invokeAttr, Object target, Object[] args, Boolean[] byrefModifiers, Int32 culture, String[] namedParameters)\r\n at System.RuntimeType.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters)\r\n at System.Type.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args)\r\n at System.Web.Mail.LateBoundAccessHelper.CallMethod(Type type, Object obj, String methodName, Object[] args)\r\n at System.Web.Mail.LateBoundAccessHelper.CallMethod(Object obj, String methodName, Object[] args)\r\n --- End of inner exception stack trace ---\r\n at System.Web.Mail.LateBoundAccessHelper.CallMethod(Object obj, String methodName, Object[] args)\r\n at System.Web.Mail.CdoSysHelper.Send(MailMessage message)\r\n at System.Web.Mail.SmtpMail.Send(MailMessage message)\r\n at itware.sab.shop.eventmonitoring.mailer.Mailer.SendIt(String from, String to, String cc, String bcc, String subject, String body) in d:\\development\\projects\\sab\\itware.sab.shop.eventlogservice\\service\\mailer.cs:line 41\r\n at itware.sab.shop.eventmonitoring.mailer.Mailer.SendIt(String from, String to, String subject, String body) in d:\\development\\projects\\sab\\itware.sab.shop.eventlogservice\\service\\mailer.cs:line 20\r\n at itware.sab.shop.eventmonitoring.service.EventsMonitor.DoUnsent() in d:\\development\\projects\\sab\\itware.sab.shop.eventlogservice\\service\\eventsmonitor.cs:line 220"
 
*sigh*
 
why is it that people insist on using the .InnerException property?
Isn't it accepted best practise not to use InnerExceptions unless you ABSOLUTELY have to?
 
what do others think about “hiding exceptions” inside nested InnerExceptions?
me; i'd prefer them out there in the open and in my face ... at least that way i know right off where i screwed up.
this simple little problem cost me hours of reading and investigating when i could've solved the problem in minutes if i'd known the REAL error upfront.
 
whilst i was digging around i stumbled across http://www.systemwebmail.com/default.aspx ; what a gem of a site ... it has everything you could ever want to know about that joyful little namespace System.Web.Mail.
 
well happy emailing everybody!
Posted: Apr 06 2005, 03:00 PM by Ryan CrawCour | with 2 comment(s)
Filed under:
Changing an icon at runtime using an ImageList control

so, ever wanted to know just how to do this?

I found myself today pulling out what little hair I have left trying to do just this; eventually I found the solution but it was not obvious!
So being the nice person I am I decided to spare all you folk some hair and tell you how to do it, aint I nice?!?

Thinking this should be no problem at all I tried the following;
this.Icon = (Icon)imageList1.Images[0];

Unfortuantely my nice C# compiler decided that it could not
"Convert System.Drawing.Image to System.Drawing.Icon"

After much trauma, and many compile errors I eventually got this;

this.Icon = Icon.FromHandle(((Bitmap)imageList1.Images[0]).GetHicon());

Not exactly elegant or obvious ...

Anybody got a better way to do this?

Posted: Apr 04 2005, 05:40 PM by Ryan CrawCour | with 2 comment(s)
Filed under:
let's do the hokey pokey ...
This is far too geeky, even for me!!
 
 
Hokey Spokes make a set of LED blades that attach to a bicycle's spokes allowing you to spell out words and make poor images while you ride on around town knowing full well just how idiotic they make you look. The blades communicate with each other using infrared and are actually programmed with your Palm, so you can make changes whilst on a ride.