-
Notifications
You must be signed in to change notification settings - Fork 406
Refactored the IQuantity interface
#1587
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…ce and the ToString overloads - introduced IAffineQuantity (see Temperature), ILogarithmicQuantity (see AmplitudeRatio) and ILinearQuantity (see Mass) - introduced extension methods for Equals with tolerance as well as Sum/Average
|
@angularsen This is the most minimalist version of the interface, applicable to the current code-base (which relies on the
This definition applies only to the /// <summary>
/// <para>
/// Compare equality to <paramref name="other"/> given a <paramref name="tolerance"/> for the maximum allowed +/- difference.
/// </para>
/// <example>
/// In this example, the two quantities will be equal if the value of b is within 0.01 of a (0.01m or 1cm).
/// <code>
/// var a = Length.FromMeters(2.0);
/// var b = Length.FromMeters(2.1);
/// var tolerance = Length.FromCentimeters(10);
/// a.Equals(b, tolerance); // true, 2m equals 2.1m +/- 0.1m
/// </code>
/// </example>
/// <para>
/// It is generally advised against specifying "zero" tolerance, due to the nature of floating-point operations.
/// </para>
/// </summary>
/// <param name="other">The other quantity to compare to.</param>
/// <param name="tolerance">The absolute tolerance value. Must be greater than or equal to zero.</param>
/// <returns>True if the absolute difference between the two values is not greater than the specified tolerance.</returns>
bool Equals(TSelf? other, TSelf tolerance);For the bool Equals(TSelf? other, TOffset tolerance); |
angularsen
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't get to the end and have to run, but here are comments so far.
| } | ||
|
|
||
| // // TODO see about this (I think the exception should take precedence to the null check, but the QuantityTests disagree) | ||
| // if (tolerance is not TOffset toleranceQuantity) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, argument validation should happen first, so this should throw.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh shit, I had completely forgotten about this thing..
Note that originally we had the very generic Equals(IQuantity? other, IQuantity tolerance) and the more specific Equals(TSelf? other, TSelf tolerance)
- Do we want to have an extension of type
Equals<TQuantity>(this TQuantity quantity, IQuantity? other, IQuantity tolerance)with a type check on both theotherand thetolerance, with just the second one throwing (kinda weird IMO) - Or would we rather have
Equals<TQuantity>(this TQuantity quantity, IQuantity? other, TQuantity tolerance)(withTOther tolerancefor the affine quantities): no exceptions thrown (returns false whenotheris not null or another type) - Do we want these at all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- No, that's weird to me too. I say remove it.
- Yes, I think those look useful enough. I assume you meant
TOffset tolerancefor affine quantities. - I think nr 2 is useful, unless we are already covered elsewhere that I'm not remembering?
- It seems a bit redundant to have
EqualsAbsolute(), as nr 1 and nr 2 just delegate to it. As far as I can see, the only difference is nullability. Can it simply be inlined? Or just renamed toEquals()as the absolute part in the name makes me think it serves a special purpose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand- Equals(TSelf? other, TSelf tolerance) this overload is a given, my 1) 2) 3) were alternatives for the very generic overload Equals(IQuantity? other, IQuantity tolerance). Do you mean you pick option 2) as in (TQuantity, IQuantity, TQuantity) for the non-affine and (TQuantity, IQuantity, TOffset) for the temperature (which is already the case).
Regarding 4) - so you mean you'd like me to make the EqualsAbsolute internal (it's being used by the two other overloads)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay I misread, IQuantity and TQuantity reads very similar.
- For tolerance equality, I'd generally expect the fully typed
TQuantityexperience, for bothotherandtoleranceto matchthis. AndTOffsetfor affine. - But I guess, why not also allow untyped
IQuantityand do type checking internally. It may be useful in certain cases and it costs us little to add. The only thing I'm unsure of, is whether it can trip up intellisense, auto-complete and AI coding assistance to not prefer the typedTQuantity. - Rename
EqualsAbsolutetoEquals, if it works without issues, or make itprivateif it's only intended to be used by the other extension methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in bdf04d5 - please double-check the signatures of the Equals extensions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ref nr 2, see comment:
bdf04d5#r163347229
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The link doesn't work, but I read it in the notification:
public static bool Equals(this IQuantity quantity, IQuantity? other, IQuantity tolerance)
This is only going to work if only one of the extensions is visible- (IQuantity, IQuantity, IQuantity) would be ambiguous with (TQuantity, TQuantity, TQuantity)..
angularsen
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Final batch of comments
| /// </summary> | ||
| /// <typeparam name="TSelf">The type itself, for the CRT pattern.</typeparam> | ||
| /// <typeparam name="TUnitType">The underlying unit enum type.</typeparam> | ||
| public interface IArithmeticQuantity<TSelf, TUnitType> : IQuantity<TSelf, TUnitType> | ||
| public interface IArithmeticQuantity<TSelf, TUnitType> : IQuantity<TSelf, TUnitType>, ILinearQuantity<TSelf> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it'll be more to clear to name it ILinearArithmeticQuantity, if it's arithmetic is for linear quantities.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean to rename the IArithmeticQuantity interface (which would be a breaking change) or the ILinearQuantity interface?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha, no I meant renaming IArithmeticQuantity to ILinearArithmeticQuantity since it's now scoped to only linear quantities, where as before it covered all quantities.
Or is it just that we haven't implemented for affine/logarithmic yet, but this may come later?
We can discuss this more later, not important.
…arison class - Temperature: removed the [Obsolete] methods - added the missing tests for the Linear/Affine/Logarithmic extensions
|
LGTM and ready to merge, if you want to address any of the open comments before you merge just do so. |
As discussed in #1587, these are supposed to go away in `v6`
- replaced the type of the tolerance parameter of the Equals extension with the concrete quantity type
…evant usages from the benchmarks
I've addressed most of the issues, with the exception of the |
|
Not that anyone cares about size, but in case you're curious- here's the before and after:
|
|
@angularsen Actually there two more extensions that I could have used here: public static TQuantity ToUnit<TQuantity>(this TQuantity quantity, UnitSystem unitSystem)
where TQuantity : IQuantityOfType<TQuantity>and public static double As<TQuantity>(this TQuantity quantity, UnitSystem unitSystem)
where TQuantity : IQuantitytell me if you rather have them here, or in a separate PR. In the 🐲 I have these in a separate file: |
Separate PR, let's get this bad boy merged. Easier to discuss smaller changes. |
|
I'll just merge this for now. |
IQuantityinterface: removed theEqualswith tolerance and theToStringoverloadsIAffineQuantity(seeTemperature),ILogarithmicQuantity(seeAmplitudeRatio) andILinearQuantity(seeMass)Equalswith tolerance as well asSumandAverage(as applicable)GetHashCodemethod with a call to a better optimized function in theComparisonclassSum/AveragefromUnitMath(replaced be the new extension methods using the more concrete definitions)GenericMathExtensionsclass as[Obsolete](replaced by the new extension methods)fixes #1461