-1

Function CarbonEquivalentFactor below contained a bug where the result was rounded to the nearest integer, instead of a decimal value of double type.

public double CarbonEquivalentFactor(int fromNoCarbonAtoms, int toNoCarbonAtoms)
{
    return fromNoCarbonAtoms / toNoCarbonAtoms;
}

Adding a type cast to one of the variables works and the function returns a correct decimal value as a double

public double CarbonEquivalentFactor(int fromNoCarbonAtoms, int toNoCarbonAtoms)
{
    return (double)fromNoCarbonAtoms / toNoCarbonAtoms;
}

It seems logical that it would be correct to add a type cast to both operands, like below:

public double CarbonEquivalentFactor(int fromNoCarbonAtoms, int toNoCarbonAtoms)
{
    return (double)fromNoCarbonAtoms / (double)toNoCarbonAtoms;
}

However then Visual Studio gives me the IDE0004 hint, "Remove unnecessary cast". Compiling and executing the function with both type casts also re-introduces the same bug i.e. the result is rounded to nearest integer.

Why is this so?

The project is in .NET standard 2.0. I'm using MS Test framework 2.1.1 in a .NET Core 3.1 project to unit test the function.

[DataTestMethod]
[DataRow(5, 1)]
[DataRow(3, 1)]
[DataRow(1, 3)]
[DataRow(0, 1)]
[DataRow(2, -1)]
[DataRow(-2, -2)]
[DataRow(3242424, 9343243)]
public void CarbonEquivalentFactorTest(int from, int to)
{
    var result = Emission.CarbonEquivalentFactor(from, to);
    var resultNET= emissionsNET.CarbonEquivalentFactor(from, to);
    Assert.AreEqual(result, resultNET);
}

The Emission class is a COM object in C++ and the other emissionsNET is .NET class ported to C#. The .NET function returns 0 when parameters are 1 and 3. And when having double type cast on both operands in division as below:

public double CarbonEquivalentFactor(int fromNoCarbonAtoms, int toNoCarbonAtoms)
{
    return (double)fromNoCarbonAtoms / (double)toNoCarbonAtoms;
}

UPDATE It must have been something with my setup or some glitch in Visual Studio. Now I can't reproduce the above bug, and the function returns 0.3333 when in parameters are 1 and 3. Anyway thanks for the time and help! I have at least sharpened my C# skills a bit today.

Johan Ahlqvist
  • 336
  • 2
  • 14
  • It isn't a bug, it a rule of [division](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/arithmetic-operators#division-operator-) in C# – Pavel Anikhouski Feb 18 '21 at 16:58
  • I made this unit test with `var result = (double)from/ to;` instead of calling the C++ method I don't have. The test passed. I also debugged and single stepped it and inspected the results. `[DataRow(1, 3)]` definitely returns `0.33333333333333331` for the .NET variant having two casts to `double`. – Olivier Jacot-Descombes Feb 18 '21 at 17:48

1 Answers1

3

C# cannot perform an arithmetic operation on two values of different types. Here, a double division must be performed, since one of the variables has been cast to double and the other is int.

Therefore, a widening cast on the other (int) operand is performed automatically.

Remove unnecessary cast (IDE0004) is just telling you that the second explicit cast is not necessary, because it is done automatically by C#. Therefore, the expressions with one and with two explicit casts are equivalent.

In fact, you can keep the second cast and the code will compile and work as expected. The hint just tells you that your code can safely be simplified.

See: Type Conversion Tables in .NET / Widening Conversions


Quick test in C# Interactive window:

> 1/3
0
> (double)1/3
0.33333333333333331
> 1/(double)3
0.33333333333333331
> (double)1/(double)3
0.33333333333333331
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188