Blue-tongue battle

Saturday, 17 October 2015

A bit of excitement in the Gardiner backyard this afternoon, when two blue-tongue lizards had a bit of a ‘rumble in the jungle’.

I assume it was a bit of a territory thing. I’d seen what I thought was one lizard sunning itself on our back steps, and noticed another one across the other side of our yard near our lemonade tree.

The latter one must have decided to go visiting because all of a sudden it was also near the steps and the first lizard wasn’t too happy about unexpected guests.

Two lizards facing off

Two lizards entangled while fighting

Two lizards tumbling down steps while fighting

After a bit of biting and hissing, the visitor made a quick getaway – but not before attracting the attention of our 3 bantam chooks (enjoying some ‘free run of the backyard’ time), who were most intrigued by the lizard and “escorted” it back across the back lawn to the garden near the lemonade tree.

Chooks look on as lizard runs away

The “steps” blue-tongue then retreated back to its spot, upon which we noticed that there was actually another lizard there too. This one must have been friendly as they both then slid behind a rock without any concerns being raised.

Blue-tongue lizard heading back to steps

Glad to say that our backyard has now returned to relative peace – that is unless you’re a worm or slater, in which case I think you’d be a bit stressed that the chooks are out to eat you Smile

4,500 kms later

Saturday, 10 October 2015

Last night we finished a two week driving holiday to the eastern states (Victoria, New South Wales and Queensland). It’s trips like this that make you realise how vast the continent of Australia is (and how nice it would be to be able to fly everywhere instead of driving!).

Map showing route from Adelaide to Brisbane and back again

It also reinforces my respect for those who choose to live and work in these remote regions.

Sunset on horizon

Highlights of the trip were the Pioneer Settlement in Swan Hill,

Pioneer Village, Swan HillBlacksmith, Swan Hill

a paddle-steamer ride in Echuca,

Paddle steamer Canberra, EchucaEchuca WharfMurray River, Echuca

more driving,

Roadside forest, NSW

a few days in a Bed and Breakfast in Grafton, NSW,

WP_20151005_005

Some fun at Dreamworld in Queensland (yes, the kids are in there with me),

DSC_8428

more driving down through the Gold Coast (No, we’re not racing),

WP_20151007_001

Before heading back home again. Our final day was from Parkes, NSW back to Adelaide – at 1,000 kms the longest distance we did in a single day.

Sunset driving back to Adelaide

It is good to be home again. Needless to say, I’m glad I’ve got a couple more days to recover before I go back to work.

It isn’t the end of my travels though. I’m off again in a couple of weeks to visit RL Solution’s Toronto office for a week, before going to my first MVP Summit at Microsoft’s campus in Seattle.

I’m an MVP!

Friday, 2 October 2015

In the early hours of this morning I received an email from Microsoft:

Dear David Gardiner,
Congratulations! We are pleased to present you with the 2015 Microsoft® MVP Award! This award is given to exceptional technical community leaders who actively share their high quality, real world expertise with others. We appreciate your outstanding contributions in ASP.NET/IIS technical communities during the past year.

It’s an award not for exceptional technical knowledge as such, but rather for “community leaders..sharing .. with others”. I’m thrilled to receive it, and hope it will help me to do even more for the developer community in the future.

Next up I’m hoping to attend the MVP Summit in Seattle in early November. It will be great to meet many of the other MVP award recipients in person (and hopefully line up some speakers for the Adelaide .NET User Group).

It’s going to be busy over the next few weeks getting ready!

Automated ATO scam phone calls

Wednesday, 30 September 2015

Yesterday and today I received some unusual calls on my mobile phone. They were both using computerised voices and claimed to be related to some legal action related to the “ATO” (presumably the Australian Tax Office). Yesterday’s call was supposedly from an “Agent John Smith”. Pretty sure the computer voice said “A-Toe”, rather than “A-T-O” too.

The calling numbers (and also the number they suggested I call them back on in the message) were:

The second number called twice as I didn’t hear or pick up the first time.

No surprises, it’s a scam - https://www.scamwatch.gov.au/news/telephone-calls-alleging-fake-arrest-warrants-used-to-scam-money

Interesting that they are calling my mobile – usually I get the “hello sir, your computer is sending us errors, would you like us to fix it” scams just on the home phone.

Casting and foreach – swings and roundabouts

Sunday, 20 September 2015

I had a good discussion the other day about a code warning that one of the new Roslyn Code Analyzers had flagged.

SonarLint comes from SonarSource, and has a whole bunch of analyzers, including this one: S3217 - "Explicit" conversions of "foreach" loops should not be used.

It is a useful warning, highlighting how the foreach instruction will cast each item for you if the collection of items is not generic. If you only use generic collections, you’ll probably never hit this – but if you ever have to deal with some of the older classes (such as the original ADO.NET types) then this may come up.

This got me curious. What does the IL (intermediate language) look like for a foreach.

The following C# code will trigger this warning:

    var table = new DataTable();

    DataRowCollection rows = table.Rows;

    foreach (var row in rows)
    {

    }

We get this IL:

  IL_0000:  nop
  IL_0001:  newobj     instance void [System.Data]System.Data.DataTable::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  callvirt   instance class [System.Data]System.Data.DataRowCollection [System.Data]System.Data.DataTable::get_Rows()
  IL_000d:  stloc.1
  IL_000e:  nop
  IL_000f:  ldloc.1
  IL_0010:  callvirt   instance class [mscorlib]System.Collections.IEnumerator [System.Data]System.Data.InternalDataCollectionBase::GetEnumerator()
  IL_0015:  stloc.2
  .try
  {
    IL_0016:  br.s       IL_0026
    IL_0018:  ldloc.2
    IL_0019:  callvirt   instance object [mscorlib]System.Collections.IEnumerator::get_Current()
    IL_001e:  castclass  [System.Data]System.Data.DataRow
    IL_0023:  stloc.3
    IL_0024:  nop
    IL_0025:  nop
    IL_0026:  ldloc.2
    IL_0027:  callvirt   instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
    IL_002c:  brtrue.s   IL_0018
    IL_002e:  leave.s    IL_0045
  }  // end .try
  finally
  {
    IL_0030:  ldloc.2
    IL_0031:  isinst     [mscorlib]System.IDisposable
    IL_0036:  stloc.s    V_4
    IL_0038:  ldloc.s    V_4
    IL_003a:  brfalse.s  IL_0044
    IL_003c:  ldloc.s    V_4
    IL_003e:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
    IL_0043:  nop
    IL_0044:  endfinally
  }  // end handler

I’m no IL guru, but it you can get the basic idea – and sure enough you can see line IL_001e, there’s a castclass operation that’s run for each item in the foreach loop.

So in this case, you can’t just explicitly cast a DataRowCollection to an IList<DataRow>. The LINQ Cast<> extension method can be used though.

This code no longer triggers the warning:

    foreach (DataRow row in rows.Cast<DataRow>())
    {

    }

And here is the corresponding IL:

  IL_0045:  nop
  IL_0046:  ldloc.1
  IL_0047:  call       class [mscorlib]System.Collections.Generic.IEnumerable`1 [System.Core]System.Linq.Enumerable::Cast(class [mscorlib]System.Collections.IEnumerable)
  IL_004c:  callvirt   instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator()
  IL_0051:  stloc.s    V_5
  .try
  {
    IL_0053:  br.s       IL_0060
    IL_0055:  ldloc.s    V_5
    IL_0057:  callvirt   instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current()
    IL_005c:  stloc.s    V_6
    IL_005e:  nop
    IL_005f:  nop
    IL_0060:  ldloc.s    V_5
    IL_0062:  callvirt   instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
    IL_0067:  brtrue.s   IL_0055
    IL_0069:  leave.s    IL_0078
  }  // end .try
  finally
  {
    IL_006b:  ldloc.s    V_5
    IL_006d:  brfalse.s  IL_0077
    IL_006f:  ldloc.s    V_5
    IL_0071:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
    IL_0076:  nop
    IL_0077:  endfinally
  }  // end handler

You can see there’s no more castcall operation, but instead notice line IL_0047. Now instead the code is calling the Cast extension method on the entire enumerable.

You might be wondering, does it make any different to performance? In this case not that I could detect. I loaded up a DataTable with 1,000,000 rows and compared execution times between the two approaches, and there wasn’t any significant difference between them.

This makes sense if you think about it – the cast needs to happen – either up front before the loop, or inside the loop. There’s no avoiding it.

So I’d say this is one warning that you shouldn’t necessarily just blindly follow. Having said that, if you’re iterating over the object more than once, then you probably will see a performance boost if you do the cast up front.