Search code examples
c#.netvariable-assignmentcode-contracts

String assignment mystic issue. Variable name affects behavior


I have the following code inside a method:

string username = (string)context["UserName"];

string un = (string)context["UserName"];

The problem is that the first string "username" is not assigned, while the second does.

To make it more strange, when I have stopped the debugging after the first line and copied the line to the Immediate window, dropping the varible type delaration, it was assigned succesfully.

I have made rebuild all and checked project properties which seems to be OK.

The context variable is a System.Configuration.SettingsContext, which is a hash table. To be more specific, I'm implementing a profile provider, the GetPropertyValues method.

I am using VS 2012 and .NET 4.5

EDIT:

I am using code contract in my project, which uses compile time code injection for runtime checking. I disabled it and all is working well. I'll try to remove contracts one by one to find which one is causing the problem.


Solution

  • What you are seeing is similar to a Code Contracts bug I saw before. I wrote something about it here a few months back. If you have this bug, you probably also have a lambda or LINQ expression in your method that uses username.

    For future reference, this is the bug I saw:

    I had in the same method a lambda expression capturing a local variable, lets say values, and a Contract.Requires() expression checking something completely unrelated. While debugging that method, the debugger shows in Locals the variable values twice, and reports the value of values always as null even when this is clearly not the case.

    To reproduce:

      static void Reproduction(string argument)
      {
          Contract.Requires(argument != null); // <-- (1)
    
          int[] values = new int[1];
          Debug.Assert(values != null);
    
          Func<int, bool> d = i => values[i] >= 0; // <-- (2)
    
          Console.WriteLine(values);
      }
    

    Put a breakpoint somewhere in this method after the assignment to values and ensure that the method gets called. When the debugger hits the breakpoint, look at the Locals list of Visual Studio for the duplicate variable. Hover the mouse over values to find that it gets reported as being null, something which is clearly not the case.

    The problem disappears when removing either the contract (1) or the line with the lambda (2).