Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does casting from byte to sbyte give a wrong value for optimized code?

Tags:

c#

.net

casting

The problem can be reproduced with the following code sample, having NUnit 3 installed.

[TestFixture]
public class SByteFixture
{
    [Test]
    public void Test()
    {
        var data = new byte[] { 0xFF };

        sbyte x = -128;
        data[0] = (byte) x;
        byte b1 = data[0];
        var b2 = (sbyte) b1;
        Assert.AreEqual(b1.ToString(), "128");
        Assert.AreEqual(b2.ToString(), "-128");
    }
}
  1. The project should be a class library because in a console application it's not reproducible.
  2. Should have optimization enabled, i.e. the following setting in the csproj file:

    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
        <Optimize>true</Optimize>
    </PropertyGroup>
    

The test passes when Optimize is false, but it fails when Optimize is true (b2.ToString() gives "128").

This can be seen using ReSharper for running the test or NUnitConsole, not reproducible with VS Test Explorer.

How can this be explained?

like image 241
Marcel Perju Avatar asked Oct 16 '18 14:10

Marcel Perju


1 Answers

As @HansPassant suggested, I've reported this issue on GitHub, and it seems to be a confirmed bug.

Here's a quote on this issue from mikedn

The fact that you can reproduce in a class library and not a console application might mean that you're using .NET Framework and not .NET Core. In .NET Framework console apps default to 32 bit so they use the legacy JIT32, not RyuJIT. 64 bit .NET Framework apps use RyuJIT but it's typically an older version than the one used by .NET Core.

I can reproduce this issue using 64 bit .NET Framework 4.7.2 but not the current master version of .NET Core. It can be reproduce using .NET Core 2.1 so it's likely that this was already fixed in master.

like image 66
Marcel Perju Avatar answered Nov 05 '22 05:11

Marcel Perju