2

Consider the following code:

I build it with .NET framework 4.7.2.

ushort[] a = new ushort[100];

if (a is short[])
{
    Assert.Fail("This never happens.");
}
object b = a;

if (b is short[])
{
    Assert.Fail("Why?");
}

The first test works as expected (a is not of short[]). My question concerns the second test, which, unexpectedly, does not fail.

Why is it so?

EDIT: added MSIL (Release, optimized)

 .maxstack  8
  IL_0000:  ldc.i4.s   100
  IL_0002:  newarr     [mscorlib]System.UInt16
  IL_0007:  isinst     int16[]
  IL_000c:  brfalse.s  IL_0018
  IL_000e:  ldstr      "Why\?"
  IL_0013:  call       void [(...).TestFramework](...).Assert::Fail(string)
  IL_0018:  ret

Surak of Vulcan
  • 348
  • 2
  • 11
  • 6
    Have a look at this [answer](https://stackoverflow.com/a/60061088/4728685) of Eric Lippert and comments to it. This [article](https://ericlippert.com/2009/03/03/representation-and-identity/) can also be helpful – Pavel Anikhouski Feb 28 '20 at 13:47
  • 3
    The point here, that CLR allows unboxing from `ushort` to `short` and vise versa, therefore the second condition is works – Pavel Anikhouski Feb 28 '20 at 13:49
  • 2
    "The first test fails" is confusing. To my mind the first test actually succeeds, because "Assert.Fail("This never happens.")" is not called. And the second test fails, because "Assert.Fail("Why?");" is called. – Polyfun Feb 28 '20 at 13:51
  • @Polyfun - I edited to make it clearer, that I wanted to distinguish between `ushort[]` and `short[]` – Surak of Vulcan Feb 28 '20 at 13:56
  • @PavelAnikhouski - so, `a is short[]` would be always `true` in the first test, were it not for optimization? – Surak of Vulcan Feb 28 '20 at 13:58
  • 1
    @SurakofVulcan it's not about `optimization`... *it's all about boxing and unboxing conversions*... – Trevor Feb 28 '20 at 14:03
  • 1
    @SurakofVulcan it's about boxing/unboxing, not about optimization – Pavel Anikhouski Feb 28 '20 at 14:04
  • 1
    @PavelAnikhouski thanks, I think I get it now, Eric Lippert's answer that you suggested makes it clear. – Surak of Vulcan Feb 28 '20 at 14:06
  • Does this answer your question? [How to cast correctly from long to int?](https://stackoverflow.com/questions/60060876/how-to-cast-correctly-from-long-to-int) – Sathish Guru V Feb 28 '20 at 14:21
  • @SathishGuru - yes, this is the post, that Pavel Anikouski suggested – Surak of Vulcan Feb 28 '20 at 14:29
  • I don't believe that there's any boxing and unboxing going on here at all - arrays are reference types and thus not subject to boxing. Even after casting a[] to a short array (via `object`), when accessing the elements of the short array there is no boxing happening. (You can verify this by inspecting the generated IL - there are no boxing instructions.) – Matthew Watson Feb 28 '20 at 14:35
  • @MatthewWatson - I added the MSIL, it really seems that `isinst` thinks that the two types are the same – Surak of Vulcan Feb 28 '20 at 14:50
  • 1
    Indeed - and it's possible to effectively "cast" an array of `ushort` to an array of `short`as shown in this [DotNet Fiddle](https://dotnetfiddle.net/lWQDgD) – Matthew Watson Feb 28 '20 at 14:56
  • 1
    I don't understand why this question is marked as duplicate. – Yacoub Massad Feb 28 '20 at 15:00
  • It's not a duplicate, at least, not of the question it's supposed to be a duplicate of. – Matthew Watson Feb 28 '20 at 15:01
  • Another fun thing is that `Console.WriteLine(b is ushort[]);` and `Console.WriteLine(b is short[]);` both print `true`... So `b` is both `short[]` AND `ushort[]`. See [this fiddle](https://dotnetfiddle.net/qAuvvd) – Matthew Watson Feb 28 '20 at 15:04
  • I believe that the correct duplicate question is: https://stackoverflow.com/questions/593730/why-does-int-is-uint-true-in-c-sharp – Matthew Watson Feb 28 '20 at 15:10

0 Answers0