Open Aniobodo opened 1 year ago
Tagging subscribers to this area: @dotnet/area-system-buffers See info in area-owners.md if you want to be subscribed.
Author: | Aniobodo |
---|---|
Assignees: | - |
Labels: | `area-System.Buffers`, `untriaged` |
Milestone: | - |
"Instead of throwing an exception like INumber.CreateChecked()"
What's wrong with INumberBase<T>.TryConvertFromChecked
(docs here)? 🤔
@Sergio0694
INumberBase
@ufcpp INumberBase.TryConvertFromChecked is protected abstract. I want the access or the implementation for primitive numeric types.
@Aniobodo TryConvertFromChecked is called from CreateChecked.
Note also TryConvertFromChecked
also can throw.
@ufcpp
@hamarb123
The exception from INumber
Here's some code that can do what you want (based on a random implementation of CreateChecked
I found):
For some reason this is legal (it's because NumberBaseExtensions.Helper
implements INumberBase`1
meaning it can access protected members on it for some reason, despite the generic parameter being wrong):
Note: the code above is probably not great due to the try/catch.
The exception from INumber.CreateChecked() is exactly the limitation. I would like to get notified about the overflow, without throwing an exception.
I was just pointing out that TryConvertFromChecked
is not a solution since it can also throw. You also should try TryConvertToChecked
.
I think this could be a good feature (as far as I can tell there is no way to do this currently, and it would clearly be faster if you didn't have to catch an exception), but it probably won't be very fast for any types that don't directly implement relevant new members and just rely on whatever default interface implementation we would have to add.
Tagging subscribers to this area: @dotnet/area-system-numerics See info in area-owners.md if you want to be subscribed.
Author: | Aniobodo |
---|---|
Assignees: | - |
Labels: | `area-System.Numerics`, `untriaged` |
Milestone: | - |
Can you elaborate on what you're trying to do and what you're going to do when the conversion fails?
We provide 3 Create
APIs because there are roughly 3 types of conversions:
The internal TryConvert*
APIs are protected only because they are "private impl" details of how Create*
work. They are expected to have very specific contracts and be used in vary specific ways to account for any T
to U
conversion. This allows some conversion to be defined almost no matter how the relationship exists between the concrete T
and U
(same assembly, different assemblies, T depends on
U,
Udepends on
T, etc). It also ensures some "deterministic" behavior in the case that both
Tand
U` define the same conversion.
Try
here also isn't Try
as in "can this be converted without throwing", it's Try
as in "is the target T/U supported".@tannergooding
What am trying to do is: simple numeric comparision of INumbers
Now let's look at the available APIs
T1.CreateChecked
T1.CreateSaturating
T1.CreateTruncating
It would likely be better/more efficient to handle this more generically rather than trying to convert between unknown types which may allocate, perform other expensive operations, or not have the behavior you expect. -- For example, the proposed approach will also not work for say floating-point
where the concept of truncation/overflow do not exist. For Single
, Half
, and Double
there is only saturation and rounding to nearest representable results and therefore some T1: double
cast to a T2: float
may silently lose precision and report "equal" when they actually aren't.
IBinaryInteger<TSelf>
and IFloatingPoint<TSelf>
expose some instance methods you can use for this. For example, you can given two binary integers you can value1.GetShortestBitLength() op value2.GetShortestBitLength()
as an early filter and only do the more expensive comparison in the case the two lengths are equal. In the case they are equal you can get the underlying bytes using [Try]WriteBigEndian
or [Try]WriteLittleEndian
to do the more exact comparison.
There are also APIs that exist on INumberBase<TSelf>
that can likewise help do efficient filtering/early exit checks, such as IsNegative
(noting that for INumber<TSelf>
these are well defined, but for INumberBase<TSelf>
which may include Complex
numbers, you can get other interesting behaviors and considerations to take into account).
Please add INumber.Create(out bool successful)
method that outputs a flag -true/false-, indicating if the creation was successful or not.
Instead of throwing an exception like INumber.CreateChecked(), just output the flag and return a default number value. Each program can then hadle the issue locally.
INumber.Create(out bool successful)
area-System.Numerics @jeffhandley