Skip to content

Commit 240b19d

Browse files
Muximizeangularsen
andauthored
Implicit cast between Duration and TimeSpan (#1365)
### Changes - Change `Duration` from explicit to implicit cast to/from `TimeSpan` - Remove operator overloads for `TimeSpan` now covered by implicit cast for all but left operands ### Background See #1354 (comment) One issue is that the operator overloads only work when `TimeSpan` is the right operand. I changed the code generation to take this into account, but another option would be to make a breaking change where we just don't support `TimeSpan` as the left operand at all. Then users would have to cast explicitly, or for multiplication just reverse the operands. This would affect 13 operators: ``` TimeSpan * Acceleration TimeSpan * ElectricCurrent TimeSpan * ElectricCurrentGradient TimeSpan * ForceChangeRate TimeSpan * KinematicViscosity TimeSpan * MassFlow TimeSpan * MolarFlow TimeSpan * Power TimeSpan * PressureChangeRate TimeSpan * RotationalSpeed TimeSpan * Speed TimeSpan * TemperatureChangeRate TimeSpan * VolumeFlow ``` Of which only 6 are used in tests so I assume are supported in v5: ``` TimeSpan * KinematicViscosity TimeSpan * MassFlow TimeSpan * Power TimeSpan * RotationalSpeed TimeSpan * TemperatureChangeRate TimeSpan * Speed ``` --------- Co-authored-by: Andreas Gullberg Larsen <[email protected]>
1 parent b4316d7 commit 240b19d

29 files changed

+16
-312
lines changed

CodeGen/Generators/QuantityRelationsParser.cs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,6 @@ public static void ParseAndApplyRelations(string rootDir, Quantity[] quantities)
5959
})
6060
.ToList());
6161

62-
// We can infer TimeSpan relations from Duration relations.
63-
var timeSpanQuantity = pseudoQuantity with { Name = "TimeSpan" };
64-
relations.AddRange(relations
65-
.Where(r => r.LeftQuantity.Name is "Duration")
66-
.Select(r => r with { LeftQuantity = timeSpanQuantity })
67-
.ToList());
68-
relations.AddRange(relations
69-
.Where(r => r.RightQuantity.Name is "Duration")
70-
.Select(r => r with { RightQuantity = timeSpanQuantity })
71-
.ToList());
72-
7362
// Sort all relations to keep generated operators in a consistent order.
7463
relations.Sort();
7564

@@ -96,9 +85,9 @@ public static void ParseAndApplyRelations(string rootDir, Quantity[] quantities)
9685
// The left operand of a relation is responsible for generating the operator.
9786
quantityRelations.Add(relation);
9887
}
99-
else if (relation.RightQuantity == quantity && relation.LeftQuantity.Name is "double" or "TimeSpan")
88+
else if (relation.RightQuantity == quantity && relation.LeftQuantity.Name is "double")
10089
{
101-
// Because we cannot add generated operators to double or TimeSpan, we make the right operand responsible in this case.
90+
// Because we cannot add operators to double we make the right operand responsible in this case.
10291
quantityRelations.Add(relation);
10392
}
10493
}

CodeGen/Generators/UnitsNetGen/QuantityGenerator.cs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -746,16 +746,6 @@ private void GenerateRelationalOperators()
746746
var rightParameter = relation.RightQuantity.Name.ToCamelCase();
747747
var rightConversionProperty = relation.RightUnit.PluralName;
748748

749-
if (relation.LeftQuantity.Name is nameof(TimeSpan))
750-
{
751-
leftConversionProperty = "Total" + leftConversionProperty;
752-
}
753-
754-
if (relation.RightQuantity.Name is nameof(TimeSpan))
755-
{
756-
rightConversionProperty = "Total" + rightConversionProperty;
757-
}
758-
759749
if (leftParameter == rightParameter)
760750
{
761751
leftParameter = "left";

UnitsNet.Tests/CustomCode/KinematicViscosityTests.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,6 @@ public static void KinematicViscosityTimesTimeSpanEqualsArea()
5656
Assert.Equal(area, Area.FromSquareMeters(8));
5757
}
5858

59-
[Fact]
60-
public static void TimeSpanTimesKinematicViscosityEqualsArea()
61-
{
62-
Area area = TimeSpan.FromSeconds(2)*KinematicViscosity.FromSquareMetersPerSecond(4);
63-
Assert.Equal(area, Area.FromSquareMeters(8));
64-
}
65-
6659
[Fact]
6760
public static void KinematicViscosityTimesDensityEqualsDynamicViscosity()
6861
{

UnitsNet.Tests/CustomCode/MassFlowTests.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,6 @@ public void MassFlowTimesTimeSpanEqualsMass()
9797
Assert.Equal(mass, Mass.FromKilograms(80.0));
9898
}
9999

100-
[Fact]
101-
public void TimeSpanTimesMassFlowEqualsMass()
102-
{
103-
Mass mass = TimeSpan.FromSeconds(4.0) * MassFlow.FromKilogramsPerSecond(20.0);
104-
Assert.Equal(mass, Mass.FromKilograms(80.0));
105-
}
106-
107100
[Fact]
108101
public void MassFlowDividedByBrakeSpecificFuelConsumptionEqualsPower()
109102
{

UnitsNet.Tests/CustomCode/PowerTests.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,6 @@ public void PowerTimesTimeSpanEqualsEnergy()
104104
Assert.Equal(energy, Energy.FromJoules(40.0));
105105
}
106106

107-
[Fact]
108-
public void TimeSpanTimesPowerEqualsEnergy()
109-
{
110-
Energy energy = TimeSpan.FromSeconds(8.0) * Power.FromWatts(5.0);
111-
Assert.Equal(energy, Energy.FromJoules(40.0));
112-
}
113-
114107
[Fact]
115108
public void PowerTimesBrakeSpecificFuelConsumptionEqualsMassFlow()
116109
{

UnitsNet.Tests/CustomCode/RotationalSpeedTests.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,5 @@ public void RotationalSpeedTimesTimeSpanEqualsAngle()
5555
Angle angle = RotationalSpeed.FromRadiansPerSecond(10.0)*TimeSpan.FromSeconds(9.0);
5656
Assert.Equal(angle, Angle.FromRadians(90.0));
5757
}
58-
59-
[Fact]
60-
public void TimeSpanTimesRotationalSpeedEqualsAngle()
61-
{
62-
Angle angle = TimeSpan.FromSeconds(9.0)*RotationalSpeed.FromRadiansPerSecond(10.0);
63-
Assert.Equal(angle, Angle.FromRadians(90.0));
64-
}
6558
}
6659
}

UnitsNet.Tests/CustomCode/SpeedTests.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,6 @@ public void SpeedTimesTimeSpanEqualsLength()
131131
Assert.Equal(length, Length.FromMeters(40));
132132
}
133133

134-
[Fact]
135-
public void TimeSpanTimesSpeedEqualsLength()
136-
{
137-
Length length = TimeSpan.FromSeconds(2)*Speed.FromMetersPerSecond(20);
138-
Assert.Equal(length, Length.FromMeters(40));
139-
}
140-
141134
[Fact]
142135
public void SpeedTimesLengthEqualsKinematicViscosity()
143136
{

UnitsNet.Tests/CustomCode/TemperatureChangeRateTests.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,6 @@ public void TemperatureChangeRateMultipliedWithTimeSpanEqualsTemperatureDelta()
3636
Assert.Equal(TemperatureDelta.FromDegreesCelsius(20), d);
3737
}
3838

39-
[Fact]
40-
public void TimeSpanMultipliedWithTemperatureChangeRateEqualsTemperatureDelta()
41-
{
42-
TemperatureDelta d = new TimeSpan(0, 0, -10) * TemperatureChangeRate.FromDegreesCelsiusPerSecond(2);
43-
Assert.Equal(TemperatureDelta.FromDegreesCelsius(-20), d);
44-
}
45-
4639
[Fact]
4740
public void TemperatureChangeRateMultipliedWithDurationEqualsTemperatureDelta()
4841
{

UnitsNet/CustomCode/Quantities/Duration.extra.cs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,19 @@ public partial struct Duration
1111
/// <summary>
1212
/// Convert a Duration to a TimeSpan.
1313
/// </summary>
14-
/// <exception cref="ArgumentOutOfRangeException">Throws if the TimeSpan can't represent the Duration exactly </exception>
14+
/// <exception cref="ArgumentOutOfRangeException">
15+
/// Throws if the duration exceeds the <see cref="TimeSpan"/>.<see cref="TimeSpan.MaxValue"/> or
16+
/// <see cref="TimeSpan.MinValue"/>, which would cause it to roll over from positive to negative and vice versa.
17+
/// </exception>
1518
/// <returns>The TimeSpan with the same time as the duration</returns>
1619
public TimeSpan ToTimeSpan()
1720
{
18-
if ( Seconds > TimeSpan.MaxValue.TotalSeconds ||
19-
Seconds < TimeSpan.MinValue.TotalSeconds )
20-
throw new ArgumentOutOfRangeException( nameof( Duration ), "The duration is too large or small to fit in a TimeSpan" );
21+
if (Seconds > TimeSpan.MaxValue.TotalSeconds) throw new ArgumentOutOfRangeException(nameof(Seconds),
22+
"The duration is too large for a TimeSpan, which would roll over from positive to negative.");
23+
24+
if (Seconds < TimeSpan.MinValue.TotalSeconds) throw new ArgumentOutOfRangeException(nameof(Seconds),
25+
"The duration is too small for a TimeSpan, which would roll over from negative to positive.");
26+
2127
return TimeSpan.FromTicks((long)(Seconds * TimeSpan.TicksPerSecond));
2228
}
2329

@@ -33,14 +39,14 @@ public TimeSpan ToTimeSpan()
3339
return time.AddSeconds(-duration.Seconds);
3440
}
3541

36-
/// <summary>Explicitly cast <see cref="Duration"/> to <see cref="TimeSpan"/>.</summary>
37-
public static explicit operator TimeSpan(Duration duration)
42+
/// <summary>Implicitly cast <see cref="Duration"/> to <see cref="TimeSpan"/>.</summary>
43+
public static implicit operator TimeSpan(Duration duration)
3844
{
3945
return duration.ToTimeSpan();
4046
}
4147

42-
/// <summary>Explicitly cast <see cref="TimeSpan"/> to <see cref="Duration"/>.</summary>
43-
public static explicit operator Duration(TimeSpan duration)
48+
/// <summary>Implicitly cast <see cref="TimeSpan"/> to <see cref="Duration"/>.</summary>
49+
public static implicit operator Duration(TimeSpan duration)
4450
{
4551
return FromSeconds(duration.TotalSeconds);
4652
}

UnitsNet/GeneratedCode/Quantities/Acceleration.g.cs

Lines changed: 0 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)