Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions standard/conversions.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,6 @@ All identity conversions are symmetric. If an identity conversion exists from `T

In most cases, an identity conversion has no effect at runtime. However, since floating point operations may be performed at higher precision than prescribed by their type ([§8.3.7](types.md#837-floating-point-types)), assignment of their results may result in a loss of precision, and explicit casts are guaranteed to reduce precision to what is prescribed by the type ([§12.9.8](expressions.md#1298-cast-expressions)).

There is an identity conversion between `nint` and `System.IntPtr`, and between `nuint` and `System.UIntPtr`.

For the compound types array, nullable type, constructed type, and tuple, there is an identity conversion between native integers ([§8.3.6](types.md#836-integral-types)) and their underlying types.

### 10.2.3 Implicit numeric conversions
Expand Down
2 changes: 2 additions & 0 deletions standard/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,8 @@ As an example of numeric promotion, consider the predefined implementations of t
```csharp
int operator *(int x, int y);
uint operator *(uint x, uint y);
nint operator *(nint x, nint y);
nuint operator *(nuint x, nuint y);
long operator *(long x, long y);
ulong operator *(ulong x, ulong y);
float operator *(float x, float y);
Expand Down
16 changes: 4 additions & 12 deletions standard/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ A struct type is a value type that can declare constants, fields, methods, prope

### 8.3.5 Simple types

Except for `nint` and `nuint`, the simple types are aliases for predefined `struct` types in the `System` namespace, as described in the table below.
The simple types are aliases for predefined `struct` types in the `System` namespace, as described in the table below.

**Keyword** | **Aliased type**
----------- | ------------------
Expand All @@ -290,8 +290,8 @@ Except for `nint` and `nuint`, the simple types are aliases for predefined `stru
`ushort` | `System.UInt16`
`int` | `System.Int32`
`uint` | `System.UInt32`
`nint` | none; see below
`nuint` | none; see below
`nint` | `System.IntPtr`
`nuint` | `System.UIntPtr`
`long` | `System.Int64`
`ulong` | `System.UInt64`
`char` | `System.Char`
Expand All @@ -300,7 +300,7 @@ Except for `nint` and `nuint`, the simple types are aliases for predefined `stru
`bool` | `System.Boolean`
`decimal` | `System.Decimal`

Every simple type has members. Each simple type that is an alias for a predefined struct type, has that struct type’s members.
Every simple type has members. Each simple type has its aliased struct type’s members.

> *Example*: `int` has any implementation-specific members declared in `System.Int32` and the members (required and implementation specific) inherited from `System.Object`, and the following statements are permitted:
>
Expand All @@ -324,14 +324,6 @@ Every simple type has members. Each simple type that is an alias for a predefine
>
> *end note*.

<!-- C# 11: In C# 11, nint and nuint become true aliases for System.IntPtr and System.UIntPtr. The following paragraphs describing the non-alias relationship should be updated or removed. -->

The types `nint` and `nuint` are represented by the types `System.IntPtr` and `System.UIntPtr`, respectively, and are *not* aliases for these types. In this context being *represented by* means:

- The only members directly accessible for `nint` and `nuint` are the required methods of `Object` ([§C.2](standard-library.md#c2-standard-library-types-defined-in-isoiec-23271)). Any other members of `System.IntPtr` and `System.UIntPtr` may be accessed via those types.
- Operations performed through `dynamic` binding on `System.IntPtr` and `System.UIntPtr` values do not have access to the `nint` and `nuint` operators.
- In all other respects `nint` and `nuint` behave as if they are aliases of `System.IntPtr` and `System.UIntPtr`.

### 8.3.6 Integral types

C# supports the following integral types, with the sizes and value ranges, as shown:
Expand Down
8 changes: 7 additions & 1 deletion standard/unsafe-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -787,22 +787,28 @@ In an unsafe context, the `+` operator ([§12.13.5](expressions.md#12135-additio
```csharp
T* operator +(T* x, int y);
T* operator +(T* x, uint y);
T* operator +(T* x, nint y);
T* operator +(T* x, nuint y);
T* operator +(T* x, long y);
T* operator +(T* x, ulong y);
T* operator +(int x, T* y);
T* operator +(uint x, T* y);
T* operator +(nint x, T* y);
T* operator +(nuint x, T* y);
T* operator +(long x, T* y);
T* operator +(ulong x, T* y);
T* operator –(T* x, int y);
T* operator –(T* x, uint y);
T* operator -(T* x, nint y);
T* operator -(T* x, nuint y);
T* operator –(T* x, long y);
T* operator –(T* x, ulong y);
long operator –(T* x, T* y);
```

There are no predefined operators for pointer addition or subtraction with native integer ([§8.3.6](types.md#836-integral-types)) offsets. Instead, `nint` and `nuint` values shall be promoted to `long` and `ulong`, respectively, with pointer arithmetic using the predefined operators for those types.

Given an expression `P` of a data pointer type `T*` and an expression `N` of type `int`, `uint`, `long`, or `ulong`, the expressions `P + N` and `N + P` compute the pointer value of type `T*` that results from adding `N * sizeof(T)` to the address given by `P`. Likewise, the expression `P – N` computes the pointer value of type `T*` that results from subtracting `N * sizeof(T)` from the address given by `P`.
Given an expression `P` of a data pointer type `T*` and an expression `N` of type `int`, `uint`, `nint`, `nuint`, `long`, or `ulong`, the expressions `P + N` and `N + P` compute the pointer value of type `T*` that results from adding `N * sizeof(T)` to the address given by `P`. Likewise, the expression `P – N` computes the pointer value of type `T*` that results from subtracting `N * sizeof(T)` from the address given by `P`.

Given two expressions, `P` and `Q`, of a data pointer type `T*`, the expression `P – Q` computes the difference between the addresses given by `P` and `Q` and then divides that difference by `sizeof(T)`. The type of the result is always `long`. In effect, `P - Q` is computed as `((long)(P) - (long)(Q)) / sizeof(T)`.

Expand Down
Loading