Tag Archives: csharp

Forgotten c-sharp language features: implicit operator

Note:  This post has been added to The Code Project at: http://www.codeproject.com/Tips/452213/Forgotten-Csharp-language-features-implicit-operat

Every now and again, I run into a situation when coding that makes me think: “Isn’t there a native c-sharp feature that does this?”  … and today I hit another one of those situations.

I was writing some code to isolate the conversion of one class to another.  I knew this conversion was going to be done in several locations throughout my codebase, so I wanted to write the conversion once and re-use that function.

My initial impulse was to write a static class and use a .Net 3.5 extension method similar to those we see when using LINQ.  I wrote some code that looked like:

public static class Converters {
    
    public static Receipt AsReceipt(this Order myOrder) {

        return new Receipt {
            // set properties in the Receipt from the Order object
        };

    }
}

I could then call this code as follows:

Receipt thisReceipt = myOrder.AsReceipt();

Clean… simple… easy.

But then it hit me: I can do this automatically with the implicit operator keywords.  Here is the link to the technical article on MSDN describing the feature:

http://bit.ly/implicitCsharp

To summarize that article: this feature allows us to define how to implicitly convert to and from an enclosing user-defined reference type (a class) with a static method.  Sweet!  I moved my code from the static “Converters” class back into the Receipt class and it now looks like:

public class Receipt {

    // other properties and methods...

    public static implicit operator Receipt(Order myOrder) {

        return new Receipt {
            // set properties in the Receipt from the Order object
        };
    }
}

and now my code to perform the conversion looks like this:

Receipt thisReceipt = myOrder;

That made my code so much easier to manage without having to litter static classes with conversion functions or use interfaces throughout my code.  As an additional benefit, now my Receipt object is now aware of how to convert to and from other types.  I prefer the isolation of this conversion logic, as it keeps me from searching my codebase to determine how best to convert from one custom type to another.

If you would prefer to be more declarative in the conversion statement, there is also an explicit operator keyword that you can use in the same fashion.  If you were to mark the conversion function as explicit operator, the usage statement would then look like this:

Receipt thisReceipt = (Receipt)myOrder;

We still maintain a very simple syntax that is descriptive of the code operation desired.  

Conclusion

These operator keywords are a powerful tool, one that many of us don’t know about or we forget that they are available to us.  Let’s try to make better use of these native language features, as they will help us improve our class design by keeping all of our object’s conversion concerns in one location.

I have a few more of these ‘forgotten features’ that I’ll highlight over the next few weeks.  I hope you check back to catch some of the other language features that I intend to discuss in the future.

Until next time, may all your code compile, and all of your unit test pass!

C-Sharp Casting of Types

This post is a response to an article from a series of posts from Iris Classon called “Stupid Questions”, and this particular article discusses the preferred way to cast types in c-sharp.  

http://www.irisclasson.com/2012/08/11/stupid-question-20-how-should-i-do-casting-in-c-should-i-use-the-prefix-cast-or-the-as-cast/

So… how should we cast a type in c-sharp?  The ‘as’ keyword gives us the capability of casting reference types without an error.  In other words, if you are attempting to cast to a type that is NOT supported by the type submitted, no error is thrown.  This is a VERY good thing.

For reference, if you are casting a value type (int, long, double, decimal) you don’t have the choice of using the “as” statement.  Instead, you will need to use a Convert.ToInt32() statement (or something similar) to change types.  However, this discussion isn’t about value types…

Consider: If you want to ensure that an object is cast properly to another type, you will need to wrap your direct cast statement in a try-catch block to ensure that no error is thrown.  Your statement will look similar to the following:

            var c = new object();

            try
            {
                var x = (Customer)c;
            }
            catch (Exception e)
            {
                Console.Out.WriteLine(e);
            }

This seems like a very simple statement, and an acceptable way to handle the scenaro.  The same operation with an “as” clause will look like:

            var c = new object();

            var x = c as Customer;
            if (x == null)
                Console.Out.WriteLine("Did not cast properly");

But lets look a little closer at the IL (Interpreted Language) generated by the compiler by these two examples.  First, the direct cast:

.locals init ([0] object c,
           [1] class CastDemo.Customer x,
           [2] class [mscorlib]System.Exception e)
  IL_0000:  nop
  IL_0001:  newobj     instance void [mscorlib]System.Object::.ctor()
  IL_0006:  stloc.0
  .try
  {
    IL_0007:  nop
    IL_0008:  ldloc.0
    IL_0009:  castclass  CastDemo.Customer
    IL_000e:  stloc.1
    IL_000f:  nop
    IL_0010:  leave.s    IL_0023
  }  // end .try
  catch [mscorlib]System.Exception 
  {
    IL_0012:  stloc.2
    IL_0013:  nop
    IL_0014:  call       class [mscorlib]System.IO.TextWriter [mscorlib]System.Console::get_Out()
    IL_0019:  ldloc.2
    IL_001a:  callvirt   instance void [mscorlib]System.IO.TextWriter::WriteLine(object)
    IL_001f:  nop
    IL_0020:  nop
    IL_0021:  leave.s    IL_0023
  }  // end handler
  IL_0023:  nop
  IL_0024:  ret

You can clearly see that the Try statement is ALWAYS fired in the first example… we will always run through the test for the exception.  In fact, the exception object is already allocated in memory on the first line!  Additionally, the call to castclass on line IL_0009 is where we attempt to make our conversion.. if no error is thrown, it jumps to line IL_0023.

… and then the IL for the “as” statement example:

  .locals init ([0] object c,
           [1] class CastDemo.Customer x,
           [2] bool CS$4$0000)
  IL_0000:  nop
  IL_0001:  newobj     instance void [mscorlib]System.Object::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  isinst     CastDemo.Customer
  IL_000d:  stloc.1
  IL_000e:  ldloc.1
  IL_000f:  ldnull
  IL_0010:  ceq
  IL_0012:  ldc.i4.0
  IL_0013:  ceq
  IL_0015:  stloc.2
  IL_0016:  ldloc.2
  IL_0017:  brtrue.s   IL_0029
  IL_0019:  call       class [mscorlib]System.IO.TextWriter [mscorlib]System.Console::get_Out()
  IL_001e:  ldstr      "Did not cast properly"
  IL_0023:  callvirt   instance void [mscorlib]System.IO.TextWriter::WriteLine(string)
  IL_0028:  nop
  IL_0029:  ret

This snippet shows that the code on line IL_0008 checks for the instance type and on line IL_0017 will exit the method if the variable is set to null.  The difference in our safety check is that the second example is directly asking if the type was converted properly, instead of relying on the try-catch to rescue us when the code doesn’t behave properly.

The performance cost of the try-catch block is trivial, a few microseconds on each call.. but the practice that is troubling here is the use of try-catch to control flow.

In computer science, we define “control flow” as the order in which coded statements are executed.  We can control flow with constructs like if, switch, and for.  If you suspect that your try-catch wrapping the cast statement is going to fail ‘regularly’ and that the catch will not truly be an ‘exceptional’ case… then you are using the try-catch to control flow.  This is considered an anti-pattern, as it changes the intent of the catch clause.

Consider:  if you have coded a catch block that traps the abstract Exception object, you have now hidden EVERYTHING that could possibly go wrong with your cast statement.  There are plenty of reasons why your cast failed, and the exception that the runtime will throw when your cast fails is System.InvalidCastException  If you need to go this route, then catch this exception, because otherwise you are hiding all kinds of events that COULD be happening to your application.

Either of these techniques is valid for casting variables.    I hope this gives some insight into what the CLR is doing when you cast types, and also demonstrate good practices when converting reference types in c-sharp

This is my first screencast in a planned series of videos that will demonstrate and discuss some unit testing and test driven development practices that I have found to be useful.  In this video, we verify that a RESTful client is communicating with a webserver by redirecting it to a hosted NancyFX server under our control.

Only 7 lines of code please

I ran across this question at Programmers.StackExchange discussing a coding guideline that states “Methods should not exceed 7 statements”.  I find these types of guidelines and the reactions to them quite amusing.

Let’s not forget the SOLID modeling principles before I begin to ramble.  Go ahead and review them for a minute.  I’ll wait…

Got it?  ok…  Programming Guidelines are written by Alpha Geeks for more intermediate and junior coders.  A rule like this one is set forth to force the uninitiated to think about how they can break down their objects and methods into much smaller, re-usable chunks.

 Consider this:  if the junior developers on your team are writing methods with 7 lines of code or less, you’re reducing the chances they’ll publish code with high cyclomatic complexity.  You’re project should end up with much simpler, less complex code just because of this rule.

Senior developers and architects who write boiler-plate code may violate this rule.  If you know WHY this rule is in place, then you know the hows, whens, and wheres about violating the 7 lines of code rule.  Those individuals are thinking about keeping complexity metrics down, and code coverage high.

Should you be writing 7 line methods?  A quick glance through one of my personal projects and the only ‘large’ methods I find are in unit tests…  and I’m okay with those.

Try using this rule for a week and see how it forces you to craft your code.  You might be surprised what you get.

Personal Asp.Net with IISExpress builds

Recently, I ran into an issue where my team wanted to run their local Asp.Net project builds so that their IISExpress instances were visible to the other team members.  This is a non-trivial setup, as a simple checkbox in the Asp.Net project properties window activates IISExpress to host the project, but does not make it visible outside of the local machine.

To configure IISExpress to answer to other names (besides localhost) the following steps are needed:

From an administrative command prompt issue the following command:  

netsh http add urlacl url=http://mymachinename:50333/ user=everyone

“mymachinename” is the hostname that you want to respond to, and 50333 is the port that Visual Studio assigned to my project.  Your port may be different, change this value to match the port that Visual Studio assigned to you.

In the applicationhost.config file at %userprofile%DocumentsIISExpressconfigapplicationhost.config find the website entry for the application you are compiling and add a binding like the following:

<binding protocol="http" bindingInformation=":50333:mymachinename" />

Finally, restart IISExpress to force the web server to re-load the settings you have just changed.  This should allow the service to answer to the appropriate host.

However, if you would like to configure Visual Studio to launch and browse to “mymachinename” instead of localhost, you need to change 1 more setting in your web project’s config.  On the “Start Action” section, set this to start with a ‘Specfic Page’ and key in the appropriate full machine name and port combination in the textbox to the right.

This preference entry is saved in the YOURWEBPROJECT.csproj.user file. By making this decision, you will allow the .csproj file to be checked in to your source control without impacting the other members of your team.