ExplicitMidpointRoundingAnalyzer 2.0.9
See the version list below for details.
dotnet add package ExplicitMidpointRoundingAnalyzer --version 2.0.9
NuGet\Install-Package ExplicitMidpointRoundingAnalyzer -Version 2.0.9
<PackageReference Include="ExplicitMidpointRoundingAnalyzer" Version="2.0.9"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="ExplicitMidpointRoundingAnalyzer" Version="2.0.9" />
<PackageReference Include="ExplicitMidpointRoundingAnalyzer"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add ExplicitMidpointRoundingAnalyzer --version 2.0.9
#r "nuget: ExplicitMidpointRoundingAnalyzer, 2.0.9"
#:package ExplicitMidpointRoundingAnalyzer@2.0.9
#addin nuget:?package=ExplicitMidpointRoundingAnalyzer&version=2.0.9
#tool nuget:?package=ExplicitMidpointRoundingAnalyzer&version=2.0.9
Explicit Midpoint Rounding Analyzer
Roslyn analyzer that reports calls to System.Math.Round, System.MathF.Round,
and System.Decimal.Round when the overload omits an explicit
MidpointRounding argument.
Math.Round defaults to MidpointRounding.ToEven, which can be easy to miss in
code reviews. This analyzer is intentionally neutral: it only requires the
rounding mode to be stated explicitly.
When this can go wrong
The default Math.Round behavior is MidpointRounding.ToEven, also known as
banker's rounding. That is a valid rounding strategy, but it can be surprising
when the code looks like ordinary "round halves up" logic.
Math.Round(2.5); // 2, not 3
Math.Round(3.5); // 4
Math.Round(4.5); // 4, not 5
This is easy to overlook in user-facing or financial calculations:
var displayedRating = Math.Round(rawRating);
var invoiceLineTotal = Math.Round(quantity * unitPrice, 2);
var taxAmount = Math.Round(netAmount * taxRate, 2);
If the intended policy is "round halves away from zero", the code should say so:
var displayedRating = Math.Round(rawRating, MidpointRounding.AwayFromZero);
var invoiceLineTotal = Math.Round(quantity * unitPrice, 2, MidpointRounding.AwayFromZero);
var taxAmount = Math.Round(netAmount * taxRate, 2, MidpointRounding.AwayFromZero);
Rule
EMRA001 reports a warning for calls such as:
Math.Round(value);
Math.Round(value, 2);
MathF.Round(floatValue);
decimal.Round(decimalValue);
System.Math.Round(value, 2);
Calls that already specify a rounding mode are ignored:
Math.Round(value, MidpointRounding.ToEven);
Math.Round(value, 2, MidpointRounding.AwayFromZero);
If the intended policy is banker's rounding, make that explicit too:
var invoiceLineTotal = Math.Round(quantity * unitPrice, 2, MidpointRounding.ToEven);
Code fix
The code fix offers both explicit rounding modes:
Math.Round(value);
// option 1
Math.Round(value, MidpointRounding.ToEven);
// option 2
Math.Round(value, MidpointRounding.AwayFromZero);
Build
To create the NuGet package locally:
dotnet pack src/ExplicitMidpointRoundingAnalyzer/ExplicitMidpointRoundingAnalyzer.csproj -c Release -o artifacts
The package version is 2.0.0 by default. CI builds automatically append the
GitHub Actions GITHUB_RUN_NUMBER or Azure Pipelines BUILD_BUILDID as the
patch version (for example, 2.0.123). You can still override the version
explicitly with -p:PackageVersion=2.0.123.
Learn more about Target Frameworks and .NET Standard.
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.