Provide a mechanism for users to expose checked and unchecked versions of their operators. #686
Replies: 7 comments
-
Did you mean I'm not sure what to think of this. Current precedent is that Also, even overcoming those hurdles, what would happen if something only had an |
Beta Was this translation helpful? Give feedback.
-
Meant it to be a secondary
It being just an implementation detail today is just the reason for this proposal. There are multiple scenarios where a user may want to define a custom type and allow the end user to determine the resulting checked/unchecked behavior. Most of these user types end up being things that are considered 'primitive', but which don't have actual runtime support (
The compiler should likely require it to be declared as a pair in order to avoid this situation. |
Beta Was this translation helpful? Give feedback.
-
I just think that this may become really confusing for newcomers when combined with 552. Someone may read your public static Int128 checked operator +(Int128 left, Int128 right);
public static Int128 unchecked operator +(Int128 left, Int128 right); and then later find some source using 552's public override unchecked int GetHashCode(); at which point they might try to put two and two together and wonder why they can't. Interactions between features (even if they're still rough proposals) should be considered, and I feel that 552 has an incredibly high chance to get implemented because it's not a lot of work for a large gain. This proposal has a bit of a conflict of interest with that. But hey, if the language team thinks that both proposals can be implemented and co-exist in perfect harmony, then by all means. |
Beta Was this translation helpful? Give feedback.
-
I think the primary difference (not to depreciate the value of 552) is that this represents a new language feature to unblock a very specific scenario that framework developers encounter. While 552 represents a way to simplify syntax and cut out 3 lines of code. public override unchecked int GetHashCode()
{
// Code
}
public override int GetHashCode()
{
unchecked
{
// Code
}
} Both have value, and both could potentially work together. However, if I had to pick one (personally), I would rather have the new language feature rather than cutting out 3 lines of code. |
Beta Was this translation helpful? Give feedback.
-
@tannergooding I don't think our proposals have to be in conflict. Your use case is not as common, so why not add new compiler-recognized attributes such as [CheckedOperator]
public static Int128 operator +(...);
[UncheckedOperator]
public static Int128 operator +(...); instead of changing the language grammar? |
Beta Was this translation helpful? Give feedback.
-
That would work as well :) |
Beta Was this translation helpful? Give feedback.
-
FYI this would also be useful for the Utf8String feature. We're considering introducing a type |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Rationale
At present, there is no way for a user to declare a type and allow consumers to dictate the checked/unchecked behavior. This makes it difficult to implement custom 'primitive' struct types (such as
Int128
).The C# language should be extended to make this possible.
Proposal
Continuing with
Int128
as the example, users should be able to declare the following:This would compile down to
op_AdditionChecked()
andop_Addition()
methods. These methods would need to be decorated with a special attribute to preserve behavior for any existing methods matching these names.Additional Details
When the
Int128 + Int128
operator is then called, it should have the following behavior:If a normalInt128 operator +(Int128 left, Int128 right);
operator is defined (that is, an operator without thechecked
orunchecked
specifier), it should be preferred (always) -- This is required to preserve back-compat.If there is no explicit checked/unchecked context (checked { }
orunchecked { }
), the operator matching the global assembly behavior should be called.If there is an explicit context, the operator matching the surrounding context should be called.op_AdditionChecked
exists, it should be calledop_Addition
is called as it always has beenAdding
op_AdditionChecked
is an explicit and potentially breaking change. It is up to the API author to decide if this is desirable or not.The default mode of
op_AdditionChecked
should bechecked
as per the required keyword,int128
would need to explicitlyuncheck
part of its operation for correct behavior.The default mode of
op_Addition
should remain that of the assembly context, unless the signature explicitly containsunchecked
in the name. This maintains back-compatOther Thoughts
It would be useful if there was a way for users to declare checked/unchecked operators and allow consumption in the scenario where they had previous defined a regular operator.
All code under a
checked operator
should be itselfchecked
by default, unless it falls into an explicitunchecked
context. The same goes forunchecked
(unchecked
by default, unless it falls into an explicitchecked
context).Beta Was this translation helpful? Give feedback.
All reactions