2007-01-15

It's not a bug, it's a feature

In my previous post I've said that I found a C# bug, now I've found out that it's not a bug, that behavior is by design.

It's written in the C# standard, around page 88 (110 real page):

[Note: As specified above, the declaration space of a block cannot share names with the declaration spaces of any nested blocks. Thus, in the following example, the F and G methods result in a compile-time error because the name i is declared in the outer block and cannot be redeclared in the inner block. However, the H and I methods are valid since the two i’s are declared in separate non-nested blocks.

class A
{
    void F() {
        int i = 0;
        if (true) {
            int i = 1;
        }
    }
    void G() {
        if (true) {
            int i = 0;
        }
        int i = 1;
    }
    void H() {
        if (true) {
            int i = 0;
        }
        if (true) {
            int i = 1;
        }
    }
    void I() {
        for (int i = 0; i < 10; i++)             H();         for (int i = 0; i < 10; i++)             H();     } }

end note]


I hate compilers that impose stupid constrains.

2007-01-10

My first C# bug

Consider this piece of code:
class Foo
{
    public static void Bar()
    {
        if (true)
        {
            int i = 0;
        }
        int i = 1; // CS0136
    }
    
    public static void Main()
    {
    }
}


Any C (C++, Java) coder will say that there is nothing wrong with that code.
I thought that was the same in C# language, I was wrong.
Here is the output from Visual Studio .NET 2003:
test.cs(9,13): error CS0136: A local variable named 'i' cannot be declared in this scope because it would give a different meaning to 'i', which is already used in a 'child' scope to denote something else

test.cs(9,13): error CS0103: The name 'i' does not exist in the class or namespace 'Foo'

Here is the output from Visual Studio 2005:
test.cs(9,13): error CS0136: A local variable named 'i' cannot be declared in this scope because it would give a different meaning to 'i', which is already used in a 'child' scope to denote something else


While VS2005 got better than VS2003, but it's still in error.

Here is what MSDN has to say about error CS0136

Compiler Error CS0136A local variable named 'var' cannot be declared in this scope because it would give a different meaning to 'var', which is already used in a 'parent or current' scope to denote something else
A variable declaration hides another declaration that would otherwise be in scope. Rename the variable that is declared on the line that generated CS0136.
The following sample generates CS0136:

// CS0136.cs
namespace x
{
   public class a
   {
      public static void Main()
      {
         int i = 0;
         {
            char i = 'a';   // CS0136, hides int i
         }
         i++;
      }
   }
}



Well, in our case i variable was declared after the if block and not before it. It doesn't make any sense to say that the second i is in the if's i scope.

I know it's a bad practice to reuse the same name for more variables in a function, but I don't expect that to be an error, just a warning at the highest warning level.

What's sad is that the alternative C# implementation, naming Mono, has the same behaviour. Here is the output:
test.cs(9,7): error CS0136: A local variable named `i' cannot be declared in this scope because it would give a different meaning to `i', which is already used in a `child' scope to denote something else
test.cs(7,8): (Location of the symbol related to previous error)


They've copied Microsoft's implementation bug by bug (for compatibility :). The sad part is that this bug was reported to Mono in 2003 but they've closed it saying it's not a bug. Here is the link to that bug

By the way I've posted a comment there, just to complain about it :)

It seems that this is not a bug, but a feature, read more about it here