Indexer

If your have a type that rep­re­sents a col­lec­tion of val­ues, adding a cus­tom indexer gives you a nat­ural way to index directly into the object using the .[ ] operator.

Take this sim­ple Cal­en­dar class for instance, which keeps a map (F# equiv­a­lent of a Dictionary<TKey, TValue>) of notes against Date­Time values:

image

By adding a cus­tom indexer here I’m now able to write code like this:

image

Also, as you may have noticed already, F# allows you to use non-integer para­me­ters in your indexer! In this case, I’m using a tuple of int * string * int. You can use this indexer from your C# code too:

image

One-Dimensional Slicer

That’s pretty cool, but we can go a step fur­ther by allow­ing you to use slicers on our types too. To allow users to get all the notes asso­ci­ated with a range of years, e.g. from 1999 to 2009, let’s add a slicer:

image

So now we can do this:

image

Two-Dimensional Slicer

Pretty awe­some, right? But what if we want to refine our search cri­te­ria even more and let you spec­ify a year range as well a range of months, e.g. get me all notes for April/May/June in the years 1999 to 2009. Thank­fully, F# lets you define a two-dimensional slicer too:

image

This two-dimensional slicer allows me to query the cal­en­dar with a year range as well as a month range:

image

As you can see, index­ers and slicers give the con­sumers of your code a much more intu­itive way to inter­act with the data encap­su­lated in your type. Keep in mind though, that F# does not allow you to add slicer with more than two dimen­sions, but I think two-dimensional slicers should be good enough for most day-to-day requirements.

Update 2011/11/08:

Swapped out my ver­bose optional argu­ment han­dling with default­Arg as Arseny Kapoulkine pointed out in the comments.

Share

I needed to find out which process is lis­ten­ing on a port the other day and a quick search on SO showed me the way and all you need is to run:

net­stat –aon | find /i “listening”

and you will get a list of the ports and the PID of the process lis­ten­ing on that port:

image 

Sweet!

Share

To get the default value of a type, you’ve prob­a­bly used the default key­word in .Net already:

   1: var defaultInt = default(int);        // 0

   2: var defaultObj = default(string);     // null

How­ever, the use of the default key­word requires a type name to be spec­i­fied at com­pile time, so you won’t be able to use it on a type which you dis­cover at run­time. Instead, you will need to do some­thing along the line of:

   1: public object GetDefaultValue(Type type)

   2: {

   3:     // Handle value types and reference types differently

   4:     if (type.IsValueType)

   5:     {

   6:         return Activator.CreateInstance(type);

   7:     }

   8:     else

   9:     {

  10:         return null;

  11:     }

  12: }

It’ll yield the same result as using the default keyword:

   1: var defaultInt = GetDefaultValue(typeof(int));        // 0

   2: var defaultObj = GetDefaultValue(typeof(string));     // null

Share

By default the GAC folder in Win­dows is located at %windir%\assembly, you can find all the reg­is­tered DLLs in that folder. Whilst you can open it in win­dows explorer and view it like any other folder, it is a some­what spe­cial and allows you to have dif­fer­ent ver­sions of the same DLL reg­is­tered in the GAC

Open up DOS prompt and nav­i­gate to the GAC folder, for instance:

image

and you can see that the GAC is actu­ally a folder inside the assem­bly folder, and drilling a lit­tle deeper reveals that each DLL has its own folder which con­tains all the reg­is­tered ver­sions, each as a folder that con­tains the actual DLL inside:

image 

image

image

.Net 4

For .Net 4, the GAC loca­tion is now %windir%\Microsoft.Net\assembly.

Global Assem­bly Cache Tool

You can use gacutil.exe from the com­mand line to view (e.g. gacu­til /l), add (e.g. gacu­til /i SomeAssembly.dll) or remove (e.g. gacu­til /u Some­Assem­bly) the con­tents of the GAC, this of course, sup­ports mul­ti­ple ver­sions of the same assem­bly too.

Share

When you’re using the Ama­zon S3 client, have you come across the occa­sional excep­tion that says some­thing like one of these excep­tion messages:

“The request was aborted: The con­nec­tion was closed unexpectedly”

“Unable to read data from the trans­port con­nec­tion: A block­ing oper­a­tion was inter­rupted by a call to WSACancelBlockingCall”

“Unable to read data from the trans­port con­nec­tion: An estab­lished con­nec­tion was aborted by the soft­ware in your host machine “

If you do, then you’re prob­a­bly attempt­ing to return the response stream directly back to the rest of your appli­ca­tion with some­thing like this:

   1: var response = _s3Client.GetObject(request);

   2: return response.ResponseStream;

How­ever, because the stream is com­ing from the Ama­zon S3 ser­vice and is fed to your code in chunks, your code needs to ensure that the con­nec­tion to S3 stays open until all the data has been received. So as men­tioned in the S3 doc­u­men­ta­tion (which inci­den­tally, most of us don’t read in great details…) here, you should be wrap­ping the response you get from the GetO­b­ject method in a using clause.

Depends on what it is you want to do with the stream, you might have to han­dle it dif­fer­ently. For instance, if you just want to read the string con­tent of a text file, you might want to do this:

   1: using (var response = _s3Client.GetObject(request))

   2: {

   3:     using (var reader = new StreamReader(response.ResponseStream))

   4:     {

   5:         return reader.ReadToEnd();

   6:     }

   7: }

Alter­na­tively, if you want to return the response stream itself, you’ll need to first load the stream in its entirety and return the loaded stream. Unfor­tu­nately, at the time of this writ­ing, the AWSSDK library still hasn’t been migrated to .Net 4 and there­fore doesn’t have the uber use­ful CopyTo method added in .Net 4, so you will most likely have to do the heavy lift­ing your­self and read the data out man­u­ally into a mem­ory stream:

   1: using (var response = _s3Client.GetObject(request))

   2: {

   3:     var binaryData = ReadFully(response.ResponseStream);

   4:     return new MemoryStream(binaryData);

   5: }

   6:

   7: /// <summary>

   8: /// See Jon Skeet's article on reading binary data:

   9: /// http://www.yoda.arachsys.com/csharp/readbinary.html

  10: /// </summary>

  11: public static byte[] ReadFully (Stream stream, int initialLength = -1)

  12: {

  13:     // If we've been passed an unhelpful initial length, just

  14:     // use 32K.

  15:     if (initialLength < 1)

  16:     {

  17:         initialLength = 32768;

  18:     }

  19:

  20:     byte[] buffer = new byte[initialLength];

  21:     int read=0;

  22:

  23:     int chunk;

  24:     while ( (chunk = stream.Read(buffer, read, buffer.Length-read)) > 0)

  25:     {

  26:         read += chunk;

  27:

  28:         // If we've reached the end of our buffer, check to see if there's

  29:         // any more information

  30:         if (read == buffer.Length)

  31:         {

  32:             int nextByte = stream.ReadByte();

  33:

  34:             // End of stream? If so, we're done

  35:             if (nextByte==-1)

  36:             {

  37:                 return buffer;

  38:             }

  39:

  40:             // Nope. Resize the buffer, put in the byte we've just

  41:             // read, and continue

  42:             byte[] newBuffer = new byte[buffer.Length*2];

  43:             Array.Copy(buffer, newBuffer, buffer.Length);

  44:             newBuffer[read]=(byte)nextByte;

  45:             buffer = newBuffer;

  46:             read++;

  47:         }

  48:     }

  49:     // Buffer is now too big. Shrink it.

  50:     byte[] ret = new byte[read];

  51:     Array.Copy(buffer, ret, read);

  52:     return ret;

  53: }

Share