BizTalk Blog by Chris Han

System Design for Enterprise Agility,

  Home  |   Contact  |   Syndication    |   Login
  67 Posts | 9 Stories | 138 Comments | 79 Trackbacks

News

Article Categories

Archives

Post Categories

Image Galleries

BizTalk Bloggers

BizTalk on MSDN

Patterns & Architecture

SharePoint

“The great power comes with a great responsibility.“

 C# as a powerful language has reduced the mistakes in Switch/Case flow control by removing the implicit fall-through behavior. That says you can not pass the compilation without an explicit statement at the end of each case, either a “break”, a “return”, a “goto”, or you can also detour the control flow by “throw” an exception. AS a matter of fact, you should always throw an out-of-boundary exception at “default” case, unless you have a default value specified by the business requirement. Otherwise it’ll be very hard to find a problem at runtime such as the caller providing a parameter which is out of the enumerator’s scope and it is being tested at the “switch” in the callee module.

 

Try code below, it is a real scenario but simplified. The root cause in this case is a bug in C# enumeration type – you can pass compile-time inspection by providing 0 even when 0 is not defined in the enumeration.

 

But if we have had a “default” case in the switch structure, it will be a lot easier to identify the problem.

 

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Diagnostics;

 

namespace WindowsApplication1

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

 

        private void Form1_Load(object sender, EventArgs e)

        {

 

        }

 

        private enum enuPath:int

        {

            a =1, // enum starts from 1, 0 is not in the scope

            b ,

            c

        }

 

 

        private void button1_Click(object sender, EventArgs e)

        {

            NewMethod(0); // C# bug: you are able to pass in 0 which is out of the scope of enuPath

        }

 

        private static void NewMethod(enuPath EnuPath)

        {           

            //int path = Convert.ToInt32(enuPath);

            try

            {

                switch (EnuPath)

                {

                    case enuPath.a:

                        Debug.WriteLine("In case 1\n");

                        break ;

 

                    case enuPath.b:

                        Debug.WriteLine("In case 2\n");

                        break;

 

                    case enuPath.c:

                        Debug.WriteLine("In case 3\n");

                        break;

                    //default:

                    //    throw new Exception("suplied parameter is out of scope of enuPath");

 

                }

                Debug.WriteLine("You are not supposed reach here since 0 is not an acceptable value\n");

            }

            catch (Exception ex)

            {

                Debug.WriteLine("In exception\n");

            }

        }

    }

}

posted on Monday, July 24, 2006 12:55 PM

Feedback

# re: Bad mix: Enumeration and Switch in C# 7/24/2006 1:52 PM Jason Coyne
Your code doesn't work as advertized, you can't just pass a 0 into your newmethod(), you would have to typecast it as an enuPath. At this point you have the problem described in your post.

Secondly, you can easily check to see if a defined value was passed in using the Enum.IsDefined() function.

The caveat to this is enums that use the [Flags] attribute. In this case, it is perfectly valid to have an enum that is a combination of values from the switch. In this case, you must do a check against each bit in the field to determine if that bit is set.

By the way, you have your case sensitivity exactly the opposite of the framework guidelines. You would declare your enum type as EnuPath, and the parameter to your function enuPath to match the framework guidelines.

# re: Bad mix: Enumeration and Switch in C# 7/25/2006 2:23 AM Random Reader
0 is the default/initial value, and is not subject to the typecast requirement.

# re: Bad mix: Enumeration and Switch in C# 8/18/2006 2:41 PM Brad
Enum.IsDefined() isn't such a great idea. See Brad Abrams blog for the reason why.
http://blogs.msdn.com/brada/archive/2003/11/29/50903.aspx

Also, everything in .NET defaults to "all bits zero" and enums are based on integer types. So you can cast enums to ints and back and enums will default with a value of 0 *by design* (ie. it isn't a bug). Generally, you want to validate your enum ranges and a switch/case/default statement is the way to go for non-flags enums. Obviously, flags create other problems for validation.

# re: Bad mix: Enumeration and Switch in C# 6/15/2007 10:55 AM DynV
witch works, just look at that code : http://www.java2s.com/Tutorial/CSharp/0040__Data-Type/Passenumtofunction.htm

I had a syntax problem using the column before the enum but I should've used it AFTER it.

# re: Bad mix: Enumeration and Switch in C# 11/20/2007 5:17 AM Name
You should always name the first enum value something like Unknown and ALWAYS have a default case in a switch!

# re: Bad mix: Enumeration and Switch in C# 7/22/2008 8:17 AM Dan Davis
I would always expect this to run:
Debug.WriteLine("You are not supposed reach here since 0 is not an acceptable value\n");

No matter what value you type in. If you used return instead of break in the switch statement it shouldn't hit it, but you didn't. If you passed 1 in, I would expect:

In case 1
You are not supposed reach here since 0 is not an acceptable value




Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification: