Archive for the '.Net' category

Method Overloading in C#

November 2, 2010 5:06 am

In the words of a 90's action movie: "Alright, pop quiz".

What would the output of the following program be:

C#:
  1. class Program
  2. {
  3.     public static void Main(string[] args)
  4.     {
  5.         int x = 0;
  6.         int y = 1;
  7.         Test(x);
  8.         Test(y);
  9.         Test(1);
  10.         Test(0);
  11.     }
  12.     public static void Test(object obj)
  13.     {
  14.         Console.WriteLine("Object Overload");
  15.     }
  16.     public static void Test(System.DayOfWeek day)
  17.     {
  18.         Console.WriteLine("Enum Overload");
  19.     }
  20. }

If you run this code under .NET 3.5 you will see the following:

Object Overload
Object Overload
Object Overload
Enum Overload

So we pass in the same type (Int32) but we end up calling different method overloads. It also seems that the specific values that we are using matters. That seems a bit counter intuitive.

What is going on? What is happening is that the C# compiler is resolving the Test(0) call to the enum overload method. The reason can be found in the C# Language Specification 4.0:

the literal 0 implicitly converts to any enum type

So the literal 0 will resolve to the enum overload method due to the implicit conversion. That is why the call with a variable set to 0 resolves to the expected object overload.

This can cause some confusion when using a class that has an enum and object overload. A common scenario is when using SqlParameter. If you specify a literal 0 to the SqlParameter constructor then it will use the overload SqlParameter(String, SqlDbType) which will set the type of the parameter and not the value and is probably not what is wanted. To get around this simply cast or convert to any object type. Since we are using an int then converting to Int32 will make our intent clear:

C#:
  1. Parameter p = new SqlParameter("@pname",
  2.     Convert.ToInt32(0));

An alternative would be to use a variable instead of a literal:

C#:
  1. private static readonly int zero = 0;
  2. ...
  3. Parameter p = new SqlParameter("@pname", zero);

Exception Shielding

July 7, 2009 4:34 am

My previous post spent over 600 words knocking down the Exception Handling Block, but version 3 and higher does have one nice feature: WCF Exception Shielding.  This allows exceptions received by a WCF service to be mapped to Fault Contracts.

Exception shielding is important in order to hide internal implementation details from service consumers.  This can make your service easier to use and, more importantly, prevent exposing sensitive internal information in your exceptions.

Enterprise Library Exception Shielding seems to be a good use of configuration to decouple a service interface from the underlying implementation.

Exception Handling (Block) & Enterprise Library

May 17, 2009 4:38 am

Lately, I've been thinking about exceptions vs. error codes. As usual, Joel On Software has a couple of well thought out posts on the topic. The first post makes the point that exceptions "create too many possible exit points for a function". The second post, Making Wrong Code Look Wrong makes some very good points on exception handling as well as other topics. In the same way that compile time errors are better than runtime errors, it is better to find errors in code simply by reading the code than by being forced to run or debug the code. That seems like a pretty straight forward statement to me but I'm wondering if people actually agree with it -- what with the popularity of various frameworks where everything is hung together with configuration files.

Those two ideas -- exceptions as flow control and making code look wrong -- led me to think about why I really, really dislike Microsoft's Enterprise Library Exception Handling Block: it combines the worst parts of both.

Consider the following:

C#:
  1. try
  2. {
  3.     DoSomething();
  4. }
  5. catch (Exception e)
  6. {
  7.     bool rethrow =
  8.         ExceptionManager.HandleException(e,
  9.             "MySpecialPolicy");
  10.  
  11.     if (rethrow)
  12.     {
  13.         throw;
  14.     }
  15. }

My objection: you have no idea what the exception handler does!

Since you can't tell what will happen at this one point, you can't mentally trace the program flow to see if it's logically sound. This makes development, tracking down bugs, and overall maintenance difficult.

"Wait, wait, wait", you say. "You can create meaningful policy names to avoid this kind of confusion". Yes, you can change the policy name to something more meaningful like "BusinessLayerMustRethrowPolicy" so you can understand the intent of the code -- which is a good thing. However, you still have no idea of the actual behavior at run time since the configuration could be set to not rethrow (for some reason). Plus, if you are making your exception handling configuration based, then you are implicitly saying that you allow the configuration to be changed to another setting (e.g. not rethrow an exception). Isn't that the point of putting things in configuration? To allow behavior to be changed without changing the code.

Since throwing an exception changes the flow of the program, if you modify the Exception Handling Block configuration (behavior) then you are actually creating a new execution path. Does that mean the program should run "properly" for all possible settings of the configuration? (Not likely!) Do you then have to test all of those possible code paths?

Maybe you could implement a policy of no configuration changes without a full test cycle but then how is that much different than performing a code change? You do skip the issue of introducing a new coding bug
and you avoid a build but you still need to create some sort of deployment package and go through a release cycle (which is the most expensive part in this lifecycle). Plus there is always the chance of the configuration becoming incorrect "by accident" and the new execution path may introduce some undesirable behavior. e.g. maybe database changes are committed because, even though an exception occurred, the policy said to not throw an exception and the calling code assumed that all errors would be reported as exceptions.

Other objections to the Exception Handling Block:

  • As a framework, the "if rethrow" construct doesn't really offer a lot of abstraction; you still need to pepper your code with "if rethrow" code in every catch block.
  • If you try to use the logging block to log an exception, every log entry for that handler shares all of the same basic log entry information (e.g. event ID). This can be restricting if you need that kind of control.

In general, I avoid the Exception Handling Application Block because it obfuscates the functioning of the program which makes the program harder to understand and maintain. To me this outweighs any functionality provided by the block.

“Project not found” problem loading a Solution with a Web Project in Visual Studio 2003 and VSS 6.0

March 7, 2007 9:20 pm

I was trying to integrate my solution which contains a web project with Visual Source Safe and was getting the message: "Unable to read the project file. The system can not find the file specified."

I found a good article on how to fix this at: http://www.inventua.com/blogs.content?EntryID=3

Unfortunately, this didn't fix my problem.

I had a variety of issues with VSS asp.net integration. What I specifically wanted to do was:

1) Have my web project be under the same directory structure as my solution (not in c:\inetpub\wwwroot)
2) Have the web location be different from the actual web project name. e.g. the web project name is Com.TestApp.UI.Web but I actually want the location to be http://localhost/TestApp and not http://localhost/Com.TestApp.UI.Web . It is possible to deploy the project to any URL but I wanted everything to be consistent in every environment.

I've read a lot of articles which helped but no one article could solve my exact issues. This is the procedure that I had to work through to get the Visual Studio/VSS integration working.

Assumptions

1) Assume solution is [my solution]
2) Assume web project is [my web project]
3) Assume virtual root name is [my virtual root] -- this may be the same as [my web project]
4) Assume user logged on is [user]

If the project has been already attempted to be loaded, we should clean up first:

Clean Up

1) Delete the VSWebCache directory C:\documents and settings\[user]\VSWebCache\[my virtual root] if it exists
2) Delete the virtual root [my virtual root] from IIS
3) delete the solution directory where [my solution] is currently located. If any files are locked perform an IISRESET and also close VSS Explorer if applicable

Configuration

1) Open up VSS Explorer. Get latest version (recursive, build tree)
2) Set permissions on the [my solution] directory. Add IIS_WPG with the following permissions: Read, Read & Execute, and List Folder Contents
3) Open [my solution]
4) The set project location dialog will open. Hit cancel.
5) Accept any other dialogs that may come up.
6) Delete the project file from the [my web project] directory.
7) Open IIS Admin and create a new virtual directory [my virtual root] that points to the directory that contains [my web project]. Accept all the defaults. Open the [my virtual root] properties page and set the Execute Permissions to Scripts Only. I did not add an application name.
8 ) Now, back in Visual Studio, open the solution from source control. (File->Source Control->Open From Source Control). Browse to the solution folder in VSS. Click overwrite when prompted.
9) The set project location dialog will open again (as in step 4). This time point to [my virtual root] and click OK.
10) As a bonus delete the directory that was created by visual studio
during step 4. This will probably be in c:\inetpub\wwwroot\[my virtual root]. It's ok to delete this because the virtual root
actually points some where else now.