-
Notifications
You must be signed in to change notification settings - Fork 392
Add conversion properties that return a quantity #1051
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
Uh oh. |
This is ready, but getting a mysterious build error.
|
I don't really understand the benefit of these conversion properties. The whole point of UnitsNet is to not care too much about the underlying values, right? So instead of your current method (which works, but is a bit verbose) why not just do: Mass mass = density * volume; And to get a raw value out at some later point: double masskg = mass.Kilograms; That is my preferred way of using UnitsNet, it makes the unit explicit when extracting a raw value. But it would be deprecated by this PR! 😧 I try to avoid using Mass othermass = mass.ToKilograms;
...
...
...
double massgrams = othermass.Value; // Surely it was grams, right? |
At first glance, I share the gut feeling of @Muximize . Adding Due to 1000+ units and binary size issues, I don't want to have both The problem; if you take a |
I think you're agreeing with me actually 😄 Encapsulation is important. These properties allow you to do conversion to a different unit and still keep encapsulation in a UnitsNet quantity as the returned type. Otherwise it's just a double (even if the quantity was not a double originally such as Currently: Volume volume = Volume.FromLiters( 3.0 );
// Surely it was cubic feet, right? ;)
double volumeInCubicFeet = volume.CubicFeet; Is now: Volume volume = Volume.FromLiters( 3.0 );
// Definitely in cubic feet ;)
Volume volumeInCubicFeet = volume.ToCubicFeet; |
This is to propose a move to this style and remove the double versions at v5. But if you just change it, it's a major breaking change with no obsolete message.
Perhaps that was a bad example. Let's go super simple: I have a length that I want to display in meters. private static string GetStringInMeters(Length length)
{
return inches.Meters; // Can't do currently: just a double
return inches.ToMeters.ToString(); // Now it's easy! It's in a UnitNet type already
} Currently your only option is: private static string GetStringInMeters(Length length)
{
return inches.ToUnit(LengthUnit.Meter).ToString();
} And getting the value is easy if you so choose: private static double GetLengthInMeters(Length length)
{
return inches.ToMeters.Value;
} What's the point of the handy conversion properties if using them loses the power of UnitsNet? |
I think it comes down to what the primary use case is.
Both are more cumbersome to get the other representation. I honestly don't know what I would consider the primary use case, and I am probably colored by many years of seeing |
But this way the encapsulation is broken. In my opinion, a quantity having a The way I use UnitsNet, there are entry points where external inputs enter the system and get "wrapped" in a quantity, eg. These entry and exit points are the only places where I care about conversion. That is the whole point of the encapsulation, that any I think the static type safety and usability of UnitsNet would improve by deprecating As for the string situation, would this be an option? private static string GetStringInMeters(Length length)
{
return length.ToString(); // Without arguments always uses BaseUnit
}
private static string GetStringInInches(Length length)
{
return length.ToString(LengthUnit.Inch);
}
The power of UnitsNet is only having to deal with conversion at the inputs and outputs, the edges of a system. |
I agree with your sentiment @Muximize, that in my use of UnitsNet I generally put values in, maybe do some arithmetic, and later get values out in a given unit. For me, that makes the most intuitive sense. However, I believe this comes down to syntax and maybe slightly on discoverability. If I understand right, we are looking at these before/after examples, so I think it is primarily a matter of syntax: // Who knows what unit, but that is fine
var parsedMass = Mass.Parse(input);
// Some arithmetic maybe
var twiceMass = parsedMass * 2;
// Before/after
var grams1 = twiceMass.Grams;
var grams2 = twiceMass.AsGrams.Value;
// Before/after
var gramsString1 = twiceMass.As(MassUnit.Gram).ToString();
var gramsString2 = twiceMass.AsGrams.ToString(); |
You're right, it's mostly a syntax thing. But I don't think it is an improvement because it makes an (in my opinion, as explained above) unfortunate feature of UnitsNet more discoverable and easier to shoot yourself in the foot with. There should be some resistance and explicitness. var parsedMass = Mass.Parse(input);
// Before/after
var someMass1 = parsedMass.ToUnit(MassUnit.Gram); // Quite explicitly changing the unit, good
var someMass2 = parsedMass.AsGrams; // Would a new user understand what they are doing?
var someMass3 = parsedMass.As(MassUnit.Gram); // Almost the same syntax, but returns a double? |
If binary size wasn't a concern, I would probably be open to having both options. I don't currently see enough benefit of changing to this new syntax style, and I agree with some of the drawbacks you outline @Muximize . It would cause a lot of breakage in people's code if v5 removed the old properties, and the benefit does not justify it for a minor syntax convenience. I vote to close this PR. |
Sorry guys has been a busy week, I haven't had time to check back in. Fine by me, you won't offend :) |
I'm glad we can part as friends 😆 Just kidding, I appreciate your ideas 🙌 |
This allows you to always get back a quantity, then reuse that quantity for other operations.
For example to calculate
Mass
and you'd use the following method:This allows for nicer conversion
It also lets you care less about if
Value
is adouble
ordecimal
. If you never need to get theValue
, it keeps you "in" a UnitsNet type.I figured I'd throw this up here now, since it would be nice to remove the current conversion properties (that assume double, even for a decimal value), as it will bloat the binary size temporarily with 2x conversion properties.