# C# Language Design Notes for May 26, 2017

## Agenda

1. Native ints

# Native ints

We would like to supply high-quality native-size integers. The best we have today is `IntPtr`, which lacks most operators and have a few behavioral weaknesses, including a suboptimal `ToString` implementation. Xamarin has introduced user-defined `nint` and `nuint` types for interop, but those can't completely do the trick; for instance, user-defined operators cannot distinguish between checked and unchecked contexts.

Options:

1. Improve `IntPtr` with operators
2. Add `nint` and `nuint` as a user defined struct (the Xamarin approach)
3. Add `nint` and `nuint` to the language
	1. compile down to `IntPtr` and add an attribute to persist the additional type info in metadata
	2. project language-level types to new user defined structs
4. A combo of 1 and 3

`IntPtr` has a few operators today; for instance `+` with `int` (which is checked on 32 bit and unchecked on 64 bit!), and some conversions.

The new structs in 3.2 look something like this:

``` c#
struct NativeInt 
{ 
	public IntPtr Value;
	public override string ToString() { ... }
}
/// etc
```

But operators are implemented by the language, not as user-defined operators.

The difference between 3.1 and 3.2 is that with 3.2 at runtime we have different types, so we can have differentiated runtime behavior: `ToString` and reflection can tell them apart.

A downside is that operations that take `ref IntPtr` (like `Interlocked.CompareExchange`) wouldn't automatically take `ref nint`. Having the public mutable field would let things still work for people, and we could go through and add `nint` overloads over time to make it better.

This should be in mscorlib, but that takes time. Is there anything we can do to mitigate in the meantime? We could ship a nuget package etc, but there's some cost to that, including indefinite maintenance. But some of the people who would benefit from this will be in a terrible spot if we don't provide something. 

We also need to deal with native float. There is no option to do 3.1 for floats; there is no `IntPtr` equivalent. So that one would need a framework type. However, we could probably live with that `nfloat` struct moving into the frameworks over time - other than Xamarin, which would add it faster for its interop scenarios.

With 3.1, if you consume a `nint`-attributed `IntPtr` with an old compiler, would it treat it as an `intPtr`? If that's the case then the code would subtly change behavior on compiler upgrade. Unfortunate! We could perhaps poison `nint` with `ModReq` so that they cannot be consumed by existing compilers, but now `nint` really *is* a different type, and requires separate overloads of methods that take it as a parameter.

Another option is to obsolete the user-defined operators on `IntPtr`, to drive people to use `nint` instead.

## Objections to 3.2:
- Adoption, where a separate struct would take a while to propagate (we feel we've mostly mitigated this)
- We'll emit slightly less efficient and more verbose IL in a couple of cases
- Needing new overloads for `nint` where there are `IntPtr` overloads today (or at least a conversion, and new overloads where there are `ref IntPtr` parameters).

Objection to 3.1:
- No runtime distinction (reflection and `ToString`)
- `ToString` happens all the time

## Conclusion
We're torn, and evenly balanced on preferring 3.1 vs 3.2. Could maybe be convinced to 3.2 if we can solve how do existing users of `IntPtr` migrate.







