Ross Coded Classes

March 1, 2010

Typesafe access to nullable DataColumns

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 3:26 pm

I recommend using these standards when reading values from a DataRow.

  • Prefer not to use the as operator with the DataRow indexer because it hides type conversion errors and it is slower than other options.
  • Use the Field extension method from System.Data.DataSetExtensions.dll for value-type columns that allow DBNull.
  • Use casting for columns that do not allow DBNull.
  • Prefer checking DataRow.IsNull and casting for nullable reference types

The extension methods Field and SetField are in System.DataSetExtensions.dll (System.Data namespace).

// Instead of using the as operator to access a DateTime? type column...
var entryDate = row["entry_date"] as DateTime?;
// Use the Field extension method instead.
var entryDate = row.Field<DateTime?>("entry_date");

All the signatures that the DataRow indexer accepts are accepted by the Field method.

It really is more of a type-safety and understanding/clarity issue than performance. Timings for 50 million calls (I recommend uses in blue) :

DateTime, AllowDBNull = true, not-null:

 row.Field<DateTime?>(column)                        4172 ms Type-safe and fastest
 row.IsNull(column) ? null : (DateTime?)row[column]  9722 ms
 row[column] as DateTime?                            9025 ms Hides InvalidCastException

DateTime, AllowDBNull = true, null:

 row.Field<DateTime?>(column)                        3935 ms Type-safe and pretty fast
 row.IsNull(column) ? null : (DateTime?)row[column]  3080 ms
 row[column] as DateTime?                            5429 ms Hides InvalidCastException

DateTime, AllowDBNull = false, not-null:

 row.Field<DateTime>(column)                         4639 ms
 (DateTime) row[column]                              2708 ms Type-safe and fast

String, AllowDBNull = false, not-null:

 row.Field<string>(column)                           3362 ms
 (string) row[column]                                1317 ms Type-safe and fast

String, AllowDBNull = true, not-null:

 row.Field<string>(column)                           3467 ms less to type, typesafe, slower.
 row.IsNull(column) ? null : (string) row[column]    2106 ms A lot to type, but fast
 row[column] as string                               1320 ms Hides InvalidCastException

String, AllowDBNull = true, null:

 row.Field<string>(column)                           2857 ms less to type, typesafe, slower.
 row.IsNull(column) ? null : (string) row[column]    1182 ms A lot to type, but fast
 row[column] as string                               1279 ms Hides InvalidCastException

September 1, 2009

DataRow.IsNull(column) is preferred over testing for DBNull.Value

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 12:27 pm

Please try to use the IsNull method on DataRow to determine if a value is null or not. DataRow/DataColumn does not actually store null or DBNull – it has a BitArray that says whether or not a non-null value is stored in which columns in the row.  Retrieving the column’s value for the row creates a copy of the DBNull.Value structure which doesn’t get created when calling the IsNull method.  Ideally this performance difference is never observable, but I feel it does tend to make the code cleaner and is the more correct implementation.


// This is better than any of the many possible 
// variations of checking the value

myDataRow.IsNull(someColumnName)

// discouraged

myDataRow[someColumnName].Equals(DBNull.Value)

myDataRow[someColumnName] == DBNull.Value

myDataRow[someColumnName] is DBNull

!(myDataRow[someColumnName] is Int32) // (or appropriate type)

September 23, 2008

Using ReSharper 4.1 to edit C# XML Documentation Comments

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 9:57 am

This is a repost of this one updated to use ReSharper 4.1…

I have recently been working on improving some of our code documentation.  I’ve found ReSharper to be very helpful in this area. (I’m using ReSharper 4.1 with the “Visual Studio” keyboard shortcuts.)
 
ReSharper’s Surround With Templates
 
I find a lot of places where paragraphs (<para>) need to be inserted, or where a member or class has been referenced by name only, and a reference using the <see> tag would be better.  One thing that I have found extremely helpful is to add my own “Surround With” templates in ReSharper.  Now I just have to highlight the text that I want to be in its own paragraph, and press Ctrl+E, U, D.  If I want to change a member name to a see tag I press Ctrl+E, U, E or use the ReSharper | Code | Surround with… menu and select the template I want.
 
Adding your own templates to ReSharper is easy:
  1. Navigate to ReSharperLive Templates… | Surround Templates.
  2. Expand User Templates.
  3. Expand C#.
  4. Click the New Template toolbar button.
  5. Fill in a Description.
  6. Choose where it will be Available by clicking the hyperlink.  For these XML code documentation comments, I choose Language-specific for C# and check Everywhere (everywhere because none of the other options seemed to work for the comments.)
  7. Edit the template text to wrap $SELECTION$ with the text you want.
  8. Choose OK.
  9. If you like, you may now choose a position for your new template in the quick access list to choose which letter it can be accessed by.  Drag your template into the list on the right to choose a shortcut.

Here are some of the Surround With templates I’ve set up for editing documentation comments:

Name Template Text
<para>
<para>$SELECTION$</para>
<see>
<see cref=”$SELECTION$”/>
<see> label
<see cref=”$SELECTION$”>$SELECTION$</see>
<note> <note type=”caution”>$SELECTION$</note>
 
I’ve found that using the template to insert the <see> tags sometimes cause ReSharper or Visual Studio to incorrectly complain that the code won’t compile by highlighting it; I can usually work normally, but if I get tired of the squiggly lines or if it gets too confused I just close the file and open it again.  I find this to be a minor inconvenience compared to the amount of time it saves.
 
ReSharper’s Live Templates
 
If you want to be able to insert text with ReSharper but you don’t want the text to surround the selection, you can use a Live Template.
 
Adding your own templates to ReSharper is pretty easy:
  1. Navigate to ReSharper | Live Templates | Live Templates.
  2. Expand User Templates.
  3. Expand C#.
  4. Click the New Template toolbar button.
  5. Fill in an shortcut and description.  (I usually set the description to the same thing as the template text since these are usually small.)
  6. Choose where it will be Available by clicking the hyperlink.  For these XML code documentation comments, I choose Language-specific for C# and check Everywhere (everywhere because none of the other options seemed to work for the comments.)
  7. Edit the template text you want to insert.
  8. Choose OK.

Here are some of the Live templates I’ve set up for editing documentation comments:

Abbreviation Template Text
seet
<see langword=”true”/>
seef
<see langword=”false”/>
seen
<see langword=”null”/>

June 17, 2008

Pop Quiz #1 Answer

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 12:30 pm
You want to read the question first.
 
In this case, the bug in the code has to do with overflow exceptions.  The value of the GetHashCode() method that all objects have can return any Int32 value, ideally there is no less chance that it returns Int32.MaxValue or Int32.MinValue than the chance that it will return a smaller number like 5.  Doing arbitrary math with the result of GetHashCode() when the code is compiled as checked can easily cause an OverflowException.
 
Even if the code were unchecked and the wrapping behavior was expected and desired, it is still not clear to someone reading the code that you want it do that.

// Throws System.OverflowException if
// ServiceName.GetHashCode() is large enough.
public override int GetHashCode()
{
      return ServiceName.GetHashCode() + DbId;
}

// Explicitly decide to let the overflow wrap
public override int GetHashCode()
{
      unchecked
      {
            return ServiceName.GetHashCode() + DbId;
      }
}

// Shorter way to explicitly let the overflow wrap
public override int GetHashCode()
{
      return unchecked(ServiceName.GetHashCode() + DbId);
}

June 16, 2008

Pop quiz #1

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 11:37 am

What could be wrong with this class?  Think carefully and post your answer in the comments. 

 

class Something
{
      public string ServiceName { get; private set; }
      public int DbId { get; private set; } 

      public Something(string serviceName, int dbId)
      {
            if (serviceName == null) throw new ArgumentNullException("serviceName");
            ServiceName = serviceName;
            DbId = dbId;
      } 

      public override int GetHashCode()
      {
            return ServiceName.GetHashCode() + DbId;
      } 

      public override bool Equals(object obj)
      {
            Something other = obj as Something;
            return other != null && DbId == other.DbId && ServiceName == other.ServiceName;
      }
}
 

April 30, 2008

Is it faster to cast or call ToString()?

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 1:10 pm

I was wondering if I already knew an object was a string if it was faster to cast it or to call ToString().  I thought it would be faster to call ToString() because casting has to do some type checking while the String class overrides ToString to return itself:


public class String
{
     //...

     public override string ToString()
     {
          return this;
     }
}

By this reasoning, I figured that (a is string && a.ToString().Length < 4000) would be cheaper than (a is string && ((string)a).Length < 4000).  

It turns out they are both six IL instructions:  

Calling ToString  

L_0007: ldloc.0
L_0008: isinst string
L_000d: brfalse.s L_0023
L_000f: ldloc.0
L_0010: callvirt instance string [mscorlib]System.Object::ToString()
L_0015: callvirt instance int32 [mscorlib]System.String::get_Length() 

Casting  

L_0025: ldloc.0
L_0026: isinst string
L_002b: brfalse.s L_0041
L_002d: ldloc.0
L_002e: castclass string
L_0033: callvirt instance int32 [mscorlib]System.String::get_Length() 

So… now what is the cost difference between the castclass operator and the virtual method call to the ToString method?  

Turns out the cast takes about 75% of the time of a ToString call. 


using System;
static class Program
{
      static void Main()
      {
            object o = "a string";
            string a;
            string b;
 
            Boolean r = (o is string && o.ToString().Length < 4000);
            r = (o is string && ((string)o).Length < 4000);
 
            DateTime t = DateTime.Now;
            for (int i = int.MinValue; i < int.MaxValue; i++)
                  a = (string)o;
            Console.WriteLine(DateTime.Now - t);
 
            t = DateTime.Now;
            for (int i = int.MinValue; i < int.MaxValue; i++)
                  b = o.ToString();
            Console.WriteLine(DateTime.Now - t);
      }
}

April 24, 2008

Using ReSharper to edit C# XML Documentation Comments

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 8:23 am
I have recently been working on improving some of our code documentation.  I’ve found ReSharper to be very helpful in this area. (I’m using ReSharper 3.1.)
 
ReSharper’s Surround With Templates
 
I find a lot of places where paragraphs (<para>) need to be inserted, or where a member or class has been referenced by name only, and a reference using the <see> tag would be better.  One thing that I have found extremely helpful is to add my own “Surround With” templates in ReSharper.  Now I just have to highlight the text that I want to be in its own paragraph, and press Ctrl+Alt+J, D.  If I want to change a member name to a see tag I press Ctrl+Alt+J, E or use the ReSharper | Code | Surround with… menu and select the template I want.
 
Adding your own templates to ReSharper is easy:
  1. Navigate to ReSharper | Options | Templates | Surround With.
  2. Expand User Templates.
  3. Click the Create Template toolbar button.
  4. Fill in a name.
  5. Choose where it will be Available by clicking the hyperlink.  For these XML code documentation comments, I choose Language-specific for C# and check Everywhere (everywhere because none of the other options seemed to work for the comments.)
  6. Edit the template text to wrap $SELECTION$ with the text you want.
  7. Choose OK.
  8. If you like, you may now choose a position for your new template in the quick access list to choose which letter it can be accessed by.

Here are some of the Surround With templates I’ve set up for editing documentation comments:

Name Template Text
<para>
<para>$SELECTION$</para>
<see>
<see cref=”$SELECTION$”/>
<see> label
<see cref=”$SELECTION$”>$SELECTION$</see>
<note> <note type=”caution”>$SELECTION$</note>
 
I’ve found that using the template to insert the <see> tags sometimes cause ReSharper or Visual Studio to incorrectly complain that the code won’t compile by highlighting it; I can usually work normally, but if I get tired of the squiggly lines or if it gets too confused I just close the file and open it again.  I find this to be a minor inconvenience compared to the amount of time it saves.
 
ReSharper’s Live Templates
 
If you want to be able to insert text with ReSharper but you don’t want the text to surround the selection, you can use a Live Template.
 
Adding your own templates to ReSharper is pretty easy:
  1. Navigate to ReSharper | Options | Templates | Live Templates.
  2. Expand User Templates.
  3. Click the Create Template toolbar button.
  4. Fill in an abbreviation and description.  (I usually set the description to the same thing as the template text since these are usually small.)
  5. Choose where it will be Available by clicking the hyperlink.  For these XML code documentation comments, I choose Language-specific for C# and check Everywhere (everywhere because none of the other options seemed to work for the comments.)
  6. Edit the template text you want to insert.
  7. Choose OK.

Here are some of the Live templates I’ve set up for editing documentation comments:

Abbreviation Template Text
seet
<see langword=”true”/>
seef
<see langword=”false”/>
seen
<see langword=”null”/>

June 26, 2007

A Hazard of Reimplementing an Explicit Interface

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 12:00 am

When implementing an interface explicitly, it is best to create virtual methods or properties if you ever expect a subclass to need to change the behavior.  Implementing the interface explicitly helps to not pollute the public members of a type, but subclasses cannot reach the superclass’s implementation if they have to reimplement the interface to change the behavior.  Exposing protected methods for the explicitly implemented members would keep the public interface clean while still allowing access by subclasses.
 
Somewhere I read a post from one of the .NET Framework developers that confirmed the superclass’s implementation would be unreachable in situations such as the one below.  You can find more on Google: http://groups.google.com/groups/search?hl=en&q=explicit+interface+base+c%23 

// Reimplementation of explicit interface implementation makes
// superclass implementation inaccessable from subclass.
 
internal class Program
{
      private static void Main()
      {
            I i = new B();
            System.Console.WriteLine(i.Stuff());
            i = new C();
            System.Console.WriteLine(i.Stuff());
      }
}
 
internal interface I
{
      int Stuff();
}
 
internal class A : I
{
      protected int count = 0;
 
      int I.Stuff()
      {
            return 1;
      }
}
 
/// <summary>
/// Normal code can't get there.
/// </summary>
internal class B : A, I
{
      int I.Stuff()
      {
            count++;
            if (count > 100)
            {
                  System.Console.WriteLine("Infinite loop");
                  return -1;
            }
 
            // Doesn't compile, not allowed to use "base" here.
            // return 2 + ((I)base).Stuff();
 
            return 2 + ((I) ((A) this)).Stuff();
      }
}
 
/// <summary>
/// Even Reflection can't get there.
/// </summary>
internal class C : A, I
{
      int I.Stuff()
      {
            count++;
            if (count > 100)
            {
                  System.Console.WriteLine("Infinite loop");
                  return -1;
            }
 
            System.Reflection.MethodInfo stuffMethodOfI;
            stuffMethodOfI = typeof (A).GetInterface("I").GetMethod("Stuff");
            return 2 + (int) stuffMethodOfI.Invoke((A) this, null);
      }
} 

 Output: 


Infinite loop
199
Infinite loop
199 

May 10, 2007

DataView RowFilter Performance

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 9:45 pm
Avoid using the default System.Data.DataView constructor followed by setting the RowFilter property.  When you want to create a System.Data.DataView object and apply a RowFilter, use the DataView constructor that takes the rowFilter parameter.  This eliminates processesing of DataRowView objects that are later removed when the RowFilter property is set.  This is particularly apparent when the DataTable has many rows and the RowFilter eliminates most of them.
 
Note that you will need to specify Sort and DataRowViewState options to use this constructor.  The defaults are an empty string for Sort and DataViewRowState.CurrentRows for RowState.
DataView slowWay = new DataView(table);
slowWay.RowFilter = rowFilter;

DataView fastWay = new DataView(table,
                                rowFilter,
                                String.Empty,
                                DataViewRowState.CurrentRows);

April 7, 2007

Create Less Garbage with EventArgs.Empty

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 6:20 pm
Create less garbage in memory by using EventArgs.Empty instead of new EventArgs().  There are other framework classes that have similar static methods, like StringComparer.InvariantCultureIgnoreCase.
 
Whenever you need to pass an EventArgs instance to something, don’t construct a new EventArgs().  Instead, use EventArgs.Empty.  I have observed certain actions in previous releases of Infragistics UltraGrid that created several hundred thousand EventArgs objects per second, adding stress to the garbage collector.
Older Posts »

Create a free website or blog at WordPress.com.