HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

String formatting of unit types

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
formattingstringunittypes

Problem

I have a units of measure library that I added string formatting to. Here is sample code:

```
[Test]
public void FormatSpeed()
{
var speed = Speed.FromMetresPerSecond(1.2);
using (Thread.CurrentThread.UsingTempCulture(CultureInfo.InvariantCulture))
{
Assert.AreEqual("1.20\u00A0m/s", speed.ToString("F2"));
Assert.AreEqual("1.20 m⋅s⁻¹", speed.ToString("F2 m⋅s⁻¹"));
Assert.AreEqual("1.2\u00A0m/s", speed.ToString());
Assert.AreEqual("1.2\u00A0m⋅s⁻¹", speed.ToString("m⋅s⁻¹"));
Assert.AreEqual("1200\u00A0mm⋅s⁻¹", speed.ToString("mm⋅s⁻¹"));
Assert.AreEqual("4.32\u00A0km/h", speed.ToString(SpeedUnit.KilometresPerHour));
Assert.AreEqual("4.3\u00A0km/h", speed.ToString("F1", SpeedUnit.KilometresPerHour));
}

var sv = CultureInfo.GetCultureInfo("sv-SE");
Assert.AreEqual("1,20\u00A0m/s", speed.ToString("F2", sv));
Assert.AreEqual("1,20 m⋅s⁻¹", speed.ToString("F2 m⋅s⁻¹", sv));
Assert.AreEqual("1,2\u00A0m/s", speed.ToString(sv));
Assert.AreEqual("1,2\u00A0m⋅s⁻¹", speed.ToString("m⋅s⁻¹", sv));
Assert.AreEqual("1200\u00A0mm⋅s⁻¹", speed.ToString("mm⋅s⁻¹", sv));
Assert.AreEqual("4,32\u00A0km/h", speed.ToString(SpeedUnit.KilometresPerHour, sv));
Assert.AreEqual("4,3\u00A0km/h", speed.ToString("F1", SpeedUnit.KilometresPerHour, sv));
}

[Test]
public void FormatAngle()
{
var angle = Angle.FromDegrees(1.2);
using (Thread.CurrentThread.UsingTempCulture(CultureInfo.InvariantCulture))
{
Assert.AreEqual("0.020943951023932\u00A0rad", angle.ToString());
Assert.AreEqual("1.200°", angle.ToString("F3°"));
Assert.AreEqual("1.2°", angle.ToString(AngleUnit.Degrees));
Assert.AreEqual(" 1.2 ° ", angle.ToString(" F1 ° "));
Assert.AreEqual(" 0.02 rad", angle.ToString(" F2 "));
Assert.AreEqual("1.200°", angle.ToString("F3", AngleUnit.Degrees));
Assert.AreEqual("0.02\u00A0rad", angle.ToString("F2", AngleUnit.Radians));
}

var

Solution

The only suggestion I would make is to extract each culture's tests to it's own unit tests. Each unit test should be testing one aspect of your code, whereas yours are each testing at least two.

Point 1: the only two overloads you need are .ToString(string) and .ToString(string, IFormatProvider). Everything else is just noise.

Point 2: you should not be adding composites like that, at all. It's just noise. If you really need that info to be passable to the .ToString call, then you should consider a third and fourth overload: .ToString(string format, string unit), and .ToString(string format, string unit, IFormatProvider formatProvider).

Point 3: I don't know enough about C# to be able to answer that exactly, but I would assume you should be using the literal space everywhere, or the \u00A0 everywhere. Pick one or the other, but don't mix-and-match.

Your unit tests have good content, but they need better names:

public void FormatSpeed_1p2_Invariant()
public void FormatSpeed_1p2_Sv_Se()
public void FormatAngle_1p2_Invariant()
public void FormatAngle_1p2_Sv_Se()


This makes it a little more clear as to what the tests are doing by name, so that when you look at the test explorer you can see you already have tests that cover certain aspects.

Code Snippets

public void FormatSpeed_1p2_Invariant()
public void FormatSpeed_1p2_Sv_Se()
public void FormatAngle_1p2_Invariant()
public void FormatAngle_1p2_Sv_Se()

Context

StackExchange Code Review Q#112075, answer score: 4

Revisions (0)

No revisions yet.