csharplang/proposals/intptr-operators.md

292 lines
10 KiB
Markdown
Raw Normal View History

2017-02-04 00:47:02 +01:00
# Operators should be exposed for `System.IntPtr` and `System.UIntPtr`
* [x] Proposed
* [ ] Prototype: Not Started
* [ ] Implementation: Not Started
* [ ] Specification: Not Started
## Summary
[summary]: #summary
The CLR supports a set of operators for the `System.IntPtr` and `System.UIntPtr` types (`native int`). These operators can be seen in `III.1.5` of the Common Language Infrastructure specification (`ECMA-335`). However, these operators are not supported by C#.
Language support should be provided for the full set of operators supported by `System.IntPtr` and `System.UIntPtr`. These operators are: `Add`, `Divide`, `Multiply`, `Remainder`, `Subtract`, `Negate`, `Equals`, `Compare`, `And`, `Not`, `Or`, `XOr`, `ShiftLeft`, `ShiftRight`.
## Motivation
[motivation]: #motivation
Today, users can easily write C# applications targeting multiple platforms using various tools and frameworks, such as: `Xamarin`, `.NET Core`, `Mono`, etc...
When writing cross-platform code, it is often necessary to write interop code that interacts with a particular target platform in a specific manner. This could include writing graphics code, calling some System API, or interacting with an existing native library.
This interop code often has to deal with handles, unmanaged memory, or even just platform-specific sized integers.
2017-05-15 19:35:24 +02:00
The runtime provides support for this by defining a set of operators that can be used on the `native int` (`System.IntPtr`) and `native unsigned int` (`System.UIntPtr`) primitive types.
2017-02-04 00:47:02 +01:00
2018-10-08 23:10:15 +02:00
C# has never supported these operators and so users have to work around the issue. This often increases code complexity and lowers code maintainability.
2017-02-04 00:47:02 +01:00
As such, the language should begin to support these operators to help advance the language to better support these requirements.
## Detailed design
[design]: #detailed-design
The full set of operators supported are defined in `III.1.5` of the Common Language Infrastructure specification (`ECMA-335`). The specification is available here: [https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-335.pdf](https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-335.pdf).
2019-03-07 19:00:39 +01:00
* A summary of the operators is provided below for convenience.
* The unverifiable operators defined by the CLI spec are not listed and are not currently part of this proposal (although it may be worth considering these as well).
2017-05-03 23:32:29 +02:00
* Providing a keyword (such as `nint` and `nuint`) nor providing a way to for literals to be declared for `System.IntPtr` and `System.UIntPtr` (such as 0n) is not part of this proposal (although it may be worth considering these as well).
2019-03-07 19:00:39 +01:00
### Unary Plus Operator
2019-03-07 19:00:39 +01:00
```csharp
System.IntPtr operator +(System.IntPtr)
```
2019-03-07 19:00:39 +01:00
```csharp
System.UIntPtr operator +(System.UIntPtr)
```
2019-03-07 19:00:39 +01:00
### Unary Minus Operator
2019-03-07 19:00:39 +01:00
```csharp
System.IntPtr operator -(System.IntPtr)
```
2019-03-07 19:00:39 +01:00
### Bitwise Complement Operator
2019-03-07 19:00:39 +01:00
```csharp
System.IntPtr operator ~(System.IntPtr)
```
2019-03-07 19:00:39 +01:00
```csharp
System.UIntPtr operator ~(System.UIntPtr)
```
2019-03-07 19:00:39 +01:00
### Cast Operators
2019-03-07 19:00:39 +01:00
```csharp
explicit operator sbyte(System.IntPtr) // Truncate
explicit operator short(System.IntPtr) // Truncate
explicit operator int(System.IntPtr) // Truncate
explicit operator long(System.IntPtr) // Sign Extend
explicit operator byte(System.IntPtr) // Truncate
explicit operator ushort(System.IntPtr) // Truncate
explicit operator uint(System.IntPtr) // Truncate
explicit operator ulong(System.IntPtr) // Zero Extend
explicit operator System.IntPtr(int) // Sign Extend
explicit operator System.IntPtr(long) // Truncate
explicit operator System.IntPtr(uint) // Sign Extend
explicit operator System.IntPtr(ulong) // Truncate
explicit operator System.IntPtr(System.IntPtr)
explicit operator System.IntPtr(System.UIntPtr)
```
2019-03-07 19:00:39 +01:00
```csharp
explicit operator sbyte(System.UIntPtr) // Truncate
explicit operator short(System.UIntPtr) // Truncate
explicit operator int(System.UIntPtr) // Truncate
explicit operator long(System.UIntPtr) // Sign Extend
explicit operator byte(System.UIntPtr) // Truncate
explicit operator ushort(System.UIntPtr) // Truncate
explicit operator uint(System.UIntPtr) // Truncate
explicit operator ulong(System.UIntPtr) // Zero Extend
explicit operator System.UIntPtr(int) // Zero Extend
explicit operator System.UIntPtr(long) // Truncate
explicit operator System.UIntPtr(uint) // Zero Extend
explicit operator System.UIntPtr(ulong) // Truncate
explicit operator System.UIntPtr(System.IntPtr)
explicit operator System.UIntPtr(System.UIntPtr)
```
2019-03-07 19:00:39 +01:00
### Multiplication Operator
2019-03-07 19:00:39 +01:00
```csharp
System.IntPtr operator *(int, System.IntPtr)
System.IntPtr operator *(System.IntPtr, int)
System.IntPtr operator *(System.IntPtr, System.IntPtr)
```
2019-03-07 19:00:39 +01:00
```csharp
System.UIntPtr operator *(uint, System.UIntPtr)
System.UIntPtr operator *(System.UIntPtr, uint)
System.UIntPtr operator *(System.UIntPtr, System.UIntPtr)
```
2019-03-07 19:00:39 +01:00
### Division Operator
2019-03-07 19:00:39 +01:00
```csharp
System.IntPtr operator /(int, System.IntPtr)
System.IntPtr operator /(System.IntPtr, int)
System.IntPtr operator /(System.IntPtr, System.IntPtr)
```
2019-03-07 19:00:39 +01:00
```csharp
System.UIntPtr operator /(uint, System.UIntPtr)
System.UIntPtr operator /(System.UIntPtr, uint)
System.UIntPtr operator /(System.UIntPtr, System.UIntPtr)
```
2019-03-07 19:00:39 +01:00
### Remainder Operator
2019-03-07 19:00:39 +01:00
```csharp
System.IntPtr operator %(int, System.IntPtr)
System.IntPtr operator %(System.IntPtr, int)
System.IntPtr operator %(System.IntPtr, System.IntPtr)
```
2019-03-07 19:00:39 +01:00
```csharp
System.UIntPtr operator %(uint, System.UIntPtr)
System.UIntPtr operator %(System.UIntPtr, uint)
System.UIntPtr operator %(System.UIntPtr, System.UIntPtr)
```
2019-03-07 19:00:39 +01:00
### Addition Operator
2019-03-07 19:00:39 +01:00
```csharp
System.IntPtr operator +(int, System.IntPtr)
System.IntPtr operator +(System.IntPtr, int)
System.IntPtr operator +(System.IntPtr, System.IntPtr)
```
2019-03-07 19:00:39 +01:00
```csharp
System.UIntPtr operator +(uint, System.UIntPtr)
System.UIntPtr operator +(System.UIntPtr, uint)
System.UIntPtr operator +(System.UIntPtr, System.UIntPtr)
```
2019-03-07 19:00:39 +01:00
### Subtraction Operator
2019-03-07 19:00:39 +01:00
```csharp
System.IntPtr operator -(int, System.IntPtr)
System.IntPtr operator -(System.IntPtr, int)
System.IntPtr operator -(System.IntPtr, System.IntPtr)
```
2019-03-07 19:00:39 +01:00
```csharp
System.UIntPtr operator -(uint, System.UIntPtr)
System.UIntPtr operator -(System.UIntPtr, uint)
System.UIntPtr operator -(System.UIntPtr, System.UIntPtr)
```
2019-03-07 19:00:39 +01:00
### Shift Operators
2019-03-07 19:00:39 +01:00
```csharp
System.IntPtr operator <<(System.IntPtr, int)
System.IntPtr operator >>(System.IntPtr, int)
```
2019-03-07 19:00:39 +01:00
```csharp
System.UIntPtr operator <<(System.UIntPtr, int)
System.UIntPtr operator >>(System.UIntPtr, int)
```
2019-03-07 19:00:39 +01:00
### Integer Comparison Operators
```csharp
bool operator ==(int, System.IntPtr)
bool operator ==(System.IntPtr, int)
bool operator ==(System.IntPtr, System.IntPtr)
bool operator !=(int, System.IntPtr)
bool operator !=(System.IntPtr, int)
bool operator !=(System.IntPtr, System.IntPtr)
bool operator <(int, System.IntPtr)
bool operator <(System.IntPtr, int)
bool operator <(System.IntPtr, System.IntPtr)
bool operator >(int, System.IntPtr)
bool operator >(System.IntPtr, int)
bool operator >(System.IntPtr, System.IntPtr)
bool operator <=(int, System.IntPtr)
bool operator <=(System.IntPtr, int)
bool operator <=(System.IntPtr, System.IntPtr)
bool operator >=(int, System.IntPtr)
bool operator >=(System.IntPtr, int)
bool operator >=(System.IntPtr, System.IntPtr)
```
2019-03-07 19:00:39 +01:00
```csharp
bool operator ==(uint, System.UIntPtr)
bool operator ==(System.UIntPtr, uint)
bool operator ==(System.UIntPtr, System.UIntPtr)
bool operator !=(uint, System.UIntPtr)
bool operator !=(System.UIntPtr, uint)
bool operator !=(System.UIntPtr, System.UIntPtr)
bool operator <(uint, System.UIntPtr)
bool operator <(System.UIntPtr, uint)
bool operator <(System.UIntPtr, System.UIntPtr)
bool operator >(uint, System.UIntPtr)
bool operator >(System.UIntPtr, uint)
bool operator >(System.UIntPtr, System.UIntPtr)
bool operator <=(uint, System.UIntPtr)
bool operator <=(System.UIntPtr, uint)
bool operator <=(System.UIntPtr, System.UIntPtr)
bool operator >=(uint, System.UIntPtr)
bool operator >=(System.UIntPtr, uint)
bool operator >=(System.UIntPtr, System.UIntPtr)
```
2019-03-07 19:00:39 +01:00
### Integer Logical Operators
2019-03-07 19:00:39 +01:00
```csharp
System.IntPtr operator &(int, System.IntPtr)
System.IntPtr operator &(System.IntPtr, int)
System.IntPtr operator &(System.IntPtr, System.IntPtr)
System.IntPtr operator |(int, System.IntPtr)
System.IntPtr operator |(System.IntPtr, int)
System.IntPtr operator |(System.IntPtr, System.IntPtr)
System.IntPtr operator ^(int, System.IntPtr)
System.IntPtr operator ^(System.IntPtr, int)
System.IntPtr operator ^(System.IntPtr, System.IntPtr)
```
2019-03-07 19:00:39 +01:00
```csharp
System.UIntPtr operator &(uint, System.UIntPtr)
System.UIntPtr operator &(System.UIntPtr, uint)
System.UIntPtr operator &(System.UIntPtr, System.UIntPtr)
System.UIntPtr operator |(uint, System.UIntPtr)
System.UIntPtr operator |(System.UIntPtr, uint)
System.UIntPtr operator |(System.UIntPtr, System.UIntPtr)
System.UIntPtr operator ^(uint, System.UIntPtr)
System.UIntPtr operator ^(System.UIntPtr, uint)
System.UIntPtr operator ^(System.UIntPtr, System.UIntPtr)
```
2017-02-04 00:47:02 +01:00
## Drawbacks
[drawbacks]: #drawbacks
The actual use of these operators may be small and limited to end-users who are writing lower level libraries or interop code. Most end-users would likely be consuming these lower level libraries themselves which would have the native sized integers, handles, and interop code abstracted away. As such, they would not have need of the operators themselves.
## Alternatives
[alternatives]: #alternatives
Have the framework implement the required operators by writing them directly in IL. Additionally, the runtime could provide intrinsic support for the operators defined by the framework, so as to better optimize the end performance.
## Unresolved questions
[unresolved]: #unresolved-questions
What parts of the design are still TBD?
## Design meetings
2019-03-07 19:00:39 +01:00
Link to design notes that affect this proposal, and describe in one sentence for each what changes they led to.