[REPOST] – Local Method Practical Example
I recently wrote about the idea of using Generic Delegates to create Local Methods (methods wholly defined within the scope of another method). Today, I had a practical application for this technique so I wanted to share it.
In this example, our task is to build a portion of an SQL update string that contains only the fields within a class that have been changed. The class stores original values and current values, so finding the changed fields is a simple matter of comparison. We are going to use a StringBuilder to construct the string. The problem comes in properly appending a comma between each name-value pair string. You cannot always add one after adding a new string since it may be the last, so the solution is to check the length of the StringBuilder before appending the string: if it is greater than 0, then we append a comma first.
The task is simple enough, but what we end up with is a lot of redundant code:
if (this.FIELD1 != this.o_FIELD1 )
{
updateString.Append( “FIELD1 = ‘” + this.FIELD1 + “’” );
}
if (updateString.Length > 0)
{
updateString.Append(“,”);
}
if (this.FIELD2 != this.o_FIELD2 )
{
updateString.Append( “FIELD2 = ‘” + this.FIELD2 + “’” );
}
if (updateString.Length > 0)
{
updateString.Append(“,”);
}
if (this.FIELD3 != this.o_FIELD3 )
{
updateString.Append( “FIELD3 = ‘” + this.FIELD3 + “’” );
}
if (updateString.Length > 0)
{
updateString.Append(“,”);
}
// Etc.
As you can see, this repeatedly defines the same behavior. It is especially aggravating when dealing with some of our legacy database tables that have hundreds of fields. While it may not be likely in this example, if we had to change this behavior it would be very tedious and some changes could easily be missed. This action is only relevant within the context of our Update method, so I really don’t want to outsource this to a private class method. Instead I will use a Generic Delegate to create a Local Method.
Since I am updating a local variable, I really don’t need to pass it: I’m going to take advantage of local variable access to reduce the parameter list and simplify the method signature. I do not need a return value, so I am going to use Action<T> to define a method that accepts a string and appends it to the StringBuilder and handles the commas as necessary. To ensure I can access the desired StringBuilder variable, I need to define it before defining my Local Method:
Action AppendUpdateString = new Action(s =>
{
if (updateString.Length > 0)
{
updateString.Append(“,”);
}
updateString.Append(s);
});
Now, I simply call the method at each desired instance (also defined after the Local Method declaration):
{
AppendUpdateString( “FIELD1 = ‘” + this.FIELD1 + “’” );
}
if (this.FIELD2 != this.o_FIELD2 )
{
AppendUpdateString( “FIELD2 = ‘” + this.FIELD2 + “’” );
}
if (this.FIELD3 != this.o_FIELD3 )
{
AppendUpdateString( “FIELD3 = ‘” + this.FIELD3 + “’” );
}
// Etc.
And this code could probably be simplified a little more, but I think this is adequate to the task. Hopefully, you’ll agree that this technique has merit. It’s very clean and easy to implement. I really like this, so much so that I am going to need to be careful to take my own advice and not go crazy with this approach.
2 little suggestion:
– StringBuilder is mutable so you can add ever the comma and then check if the string builder have a comma at the last position you will remove that
charachter
– if you put also the if in the method it’s more cleaner, for example as private methods (i’m not good with lamba expression 😦 )
CheckAppendUpdateString(
StringBuilder updateString,
string previousField,
string currentField,
string fieldName)
{
if (previous != current)
{
updateString.Append( fieldName + ” = ‘” + current + “’” );
}
if (updateString.Length > 0)
{
updateString.Append(“,”);
}
}