5

So I have this bit of code, if I break point on the return statement the immediate window outputs the information below.

try
{
    await connection.OpenAsync();
    var obj = await cmd.ExecuteScalarAsync();
    return obj != null ? Int32.Parse(obj.ToString()) != 1 : false;
}
catch (Exception ex)
{
    Log.Error("An error has occurred checking a customer/product authorization.", ex);
    return false;
}
finally
{
    connection.Close();
}

Stored Procedure Here is the relevant parts of the stored procedure. @HasAuthTable and @IsAuthorized are of the type bit.

SELECT (CASE WHEN @HasAuthTable = 0 THEN 1 ELSE 0 END) | @IsAuthorized AS IsAuthorized

Immediate Window

obj
0

obj == null
false

obj != null
false

obj == 0
error CS0019: Operator '==' cannot be applied to operands of type 'object' and 'int'

obj != 0
error CS0019: Operator '!=' cannot be applied to operands of type 'object' and 'int'

(int)obj == 0
true

(int)obj != 0
false

obj.GetType().FullName
"System.Int32"

obj.Equals(null)
false

!obj.Equals(null)
true

Object.ReferenceEquals(obj, null)
false

!Object.ReferenceEquals(obj, null)
false

I've tried Rebuilding the solution didn't change anything. I have also tried restarting Visual Studio. No luck. Is this intended behavior? It seems like a bug.

Altered Stored Procedure I tried changing the output of the stored procedure to match the following to see if it affects it in any way. The result is basically the same. static type of object with the expected dynamic type, both having values but still returning false for obj == null and obj != null.

SELECT CAST(((CASE WHEN @HasAuthTable = 0 THEN 1 ELSE 0 END) | @IsAuthorized) AS BIT) AS IsAuthorized

Respective Immediate Window

obj
false

obj != null
false

obj == null
false

obj.GetType().FullName
"System.Boolean"
Shelby115
  • 2,816
  • 3
  • 36
  • 52
  • Possible duplicate of [How can DBNull not equal DBNull](http://stackoverflow.com/questions/2060217/how-can-dbnull-not-equal-dbnull) – Eris Jul 28 '16 at 19:34
  • @Eris If the value was `DBNull.Value` then `obj` wouldn't resolve to `0` and `obj != null` would be `true` not `false`. – Servy Jul 28 '16 at 19:35
  • Use a debugger to inspect the type of obj . – Ian Jul 28 '16 at 19:40
  • @Ian It's `int`, as you can see from the edit – Servy Jul 28 '16 at 19:41
  • If it's an `int` then `obj != null` should be `true` – Matias Cicero Jul 28 '16 at 19:42
  • Hmm either it's a weird interaction with `SqlConnection/SqlCommand` or it's a visual studio bug then right? Can't say this isn't the first time Visual Studio 2015 has done really weird things (even after reinstalls). – Shelby115 Jul 28 '16 at 19:43
  • 1
    Is `obj != null` `true` when actually running the code, rather than using the debugger? – Servy Jul 28 '16 at 19:44
  • Nope. If I do `object obj = 0;` in C# interactive then `obj != null` is true, but when I run my code it still returns false. Could it be related to how I'm returning my value from the stored procedure? – Shelby115 Jul 28 '16 at 19:45
  • I suspect the immediate window has got confused because of the cast to int above. The error message error CS0019: Operator '==' cannot be applied to operands of type 'object' and 'int' suggests that it isn't an int at that stage. – Ian Jul 28 '16 at 19:48
  • 1
    @Ian No, that's based entirely on the compile time types of the left and right operands; that's all exactly what it ought to be. The only erroneous result is that `obj != null` should be `true` not `false`. – Servy Jul 28 '16 at 19:50
  • @Shelby115 what does `obj.GetType().FullName` return in the `Respective Immediate Window`? – BackDoorNoBaby Jul 28 '16 at 19:53
  • If this was JavaScript the answer would be that `obj` is `undefined` – Matias Cicero Jul 28 '16 at 19:54
  • @MatiasCicero If this was JavaScript an extra `=` symbol would probably clear this weirdness right up. – Shelby115 Jul 28 '16 at 19:55
  • See http://stackoverflow.com/questions/3507383/equalsitem-null-or-item-null -- Take away use Object.ReferenceEquals(item, null); – Alex Krupka Jul 28 '16 at 19:58
  • @Shelby115 if its a `boolean` then its not nullable, should it still be returning `true` or `false` for either of the null checks? – BackDoorNoBaby Jul 28 '16 at 19:58
  • @AlexKrupka `obj` is a variable of type `object`, so we know that there's no custom `==` operator messing this up. – Servy Jul 28 '16 at 19:59
  • @Servy `obj` is a variable of type `System.Boolean` isn't it? – BackDoorNoBaby Jul 28 '16 at 20:00
  • @BackDoorNoBaby No, it's a boxed integer. – Servy Jul 28 '16 at 20:01
  • @Servy why does the immediate window say its a boolean? – BackDoorNoBaby Jul 28 '16 at 20:04
  • @BackDoorNoBaby It depends on which immediate window you look at. There's one as an integer and one as a boolean. I've tried both it's doing it in both scenarios. ("Immedaite Window" vs "Respective Immediate Window"). – Shelby115 Jul 28 '16 at 20:05
  • @Shelby115 I imagine in the "Immediate Window" its saying that because you cast it to an `int` prior to asking for the type, but in "Respective Immediate Window" the type is `boolean` without any casting. What am I missing here? – BackDoorNoBaby Jul 28 '16 at 20:08
  • @BackDoorNoBaby These are 2 separate debugging sessions. The first is the original (integer), the second was an attempt to cast the stored procedure's output to a bit/boolean. Both end up giving me an object that has a value and type but returns false for both `obj == null` and `obj != null` which should be impossible. – Shelby115 Jul 28 '16 at 20:12
  • @Shelby115 ahh okay, my apologies for the confusion – BackDoorNoBaby Jul 28 '16 at 20:13
  • I've submitted the issue to Microsoft via `Help - Send Feedback - Report an Issue`. At this point I'm pretty confident that it is a bug with visual studio. Thank you all for confirming my suspicion. – Shelby115 Jul 28 '16 at 20:17
  • just use `return obj + "" == "1";` because `null + ""` and `DBNull.Value + ""` both result in `""` – Slai Jul 28 '16 at 23:53

1 Answers1

5

var obj = await cmd.ExecuteScalarAsync(); is doing Boxing.

enter image description here

Immediate Window displays incorrect value if 0 is boxed. It must be a bug in Immediate Window.

enter image description here

The picture is from Illustrated C# 2012 4th Edition by Daniel Solis.

Win
  • 61,100
  • 13
  • 102
  • 181
  • The immediate window reflects what happens in the code. So when it reaches `return obj != null ? Int32.Parse(obj.ToString()) != 1 : false;` `obj != null` returns false (even those it's not null). I'm aware I could technically at this point just remove the `obj != null` check but I was curious if this was some new/weird intentional behavior or a bug. – Shelby115 Jul 28 '16 at 20:16
  • 2
    Immediate windows has a bug. It doesn't match up the result if boxing value is 0. Look at the updated screenshot which return. – Win Jul 28 '16 at 20:28
  • I have [reported the Immediate window bug on the Roslyn repo](https://github.com/dotnet/roslyn/issues/12846). – svick Jul 31 '16 at 21:32