18

Can anybody shed any light on why this unit test is failing in Visual Studio 2013?

[TestMethod]
public void Inconceivable()
{
    int? x = 0;
    Assert.AreEqual(typeof(int?), x.GetType());
}
shA.t
  • 16,580
  • 5
  • 54
  • 111
Doug Clutter
  • 3,646
  • 2
  • 29
  • 31
  • Assert.IsInstanceOfType(x,typeof(int?)); – Dan Hunex Jun 22 '15 at 21:10
  • Why are you trying to assert something that's statically determined by the compiler? `x` *cannot* be anything besides an `int?` or the program wouldn't compile. – Servy Jun 22 '15 at 21:12
  • 2
    @Servy - My point was that the unit test fails when it shouldn't. Discosultan did an excellent job of explaining why. I leave it to the philosophers to debate whether GetType should or should not behave the way it does. – Doug Clutter Jun 22 '15 at 21:42
  • @Servy: To present the question. – Lightness Races in Orbit Jun 22 '15 at 23:44
  • @DougClutter And that's *my* point. When you have tests that fail because the test was written incorrectly, and not because the code being tested is actually wrong, the test has caused more harm than good. When the test *can't possibly* point out code that's not working, it can't possibly cause any good. You're only wasting your time writing such tests. – Servy Jun 23 '15 at 14:04
  • @Servy - This isn't a "real" unit test. I only wrote it to post here so my colleagues on stackoverflow could help me understand why int? worked that way. They did, so I don't consider it a waste of my time. Hopefully, others will find this post and it will help them too. Isn't that what stackoverflow is all about? – Doug Clutter Jun 23 '15 at 14:36
  • Possible duplicate of [Nullable type is not a nullable type?](http://stackoverflow.com/questions/785358/nullable-type-is-not-a-nullable-type) – Caleb Bell Sep 13 '16 at 14:25

1 Answers1

27

Your test is failing because:

Calling GetType on a Nullable type causes a boxing operation to be performed when the type is implicitly converted to Object. Therefore GetType always returns a Type object that represents the underlying type, not the Nullable type.

You can read more from How to: Identify a Nullable Type.

Some examples taken from the previous article:

int? i = 5;
Type t = i.GetType();
Console.WriteLine(t.FullName); //"System.Int32"

Also note that:

The C# is operator also operates on a Nullable's underlying type. Therefore you cannot use is to determine whether a variable is a Nullable type. The following example shows that the is operator treats a Nullable<int> variable as an int.

int? i = 5;
if (i is int) { ... } // true   

You are correct in presuming that the C# compiler is optimizing nullable types. Here's a quote from Jon Skeet's C# in Depth which should answer your question:

It’s only with respect to boxing and unboxing that the CLR has any special behavior regarding nullable types. In fact, the behavior was only changed shortly before the release of .NET 2.0, as the result of community requests.

An instance of Nullable is boxed to either a null reference (if it doesn’t have a value) or a boxed value of T (if it does). It never boxes to a “boxed nullable int”—there’s no such type.


There's a similar thread on StackOverflow: Nullable type is not a nullable type?

Community
  • 1
  • 1
Jaanus Varus
  • 3,508
  • 3
  • 31
  • 49