Enteros de tamaño nativoNative-sized integers
ResumenSummary
Compatibilidad de lenguaje para los tipos enteros con signo y sin signo de tamaño nativo.Language support for a native-sized signed and unsigned integer types.
La motivación es para los escenarios de interoperabilidad y para las bibliotecas de bajo nivel.The motivation is for interop scenarios and for low-level libraries.
DiseñoDesign
Los identificadores nint y nuint son palabras clave contextuales nuevas que representan tipos de enteros con signo y sin signo nativos.The identifiers nint and nuint are new contextual keywords that represent native signed and unsigned integer types.
Los identificadores solo se tratan como palabras clave cuando la búsqueda de nombres no encuentra un resultado viable en la ubicación del programa.The identifiers are only treated as keywords when name lookup does not find a viable result at that program location.
nint x = 3;
string y = nameof(nuint);
_ = nint.Equals(x, 3);
Los tipos nint y nuint se representan mediante los tipos subyacentes System.IntPtr y System.UIntPtr con la exposición de compiladores y las operaciones de conversiones adicionales para esos tipos como ints nativos.The types nint and nuint are represented by the underlying types System.IntPtr and System.UIntPtr with compiler surfacing additional conversions and operations for those types as native ints.
ConstantesConstants
Las expresiones constantes pueden ser de tipo nint o nuint .Constant expressions may be of type nint or nuint.
No hay ninguna sintaxis directa para los literales native int.There is no direct syntax for native int literals. En su lugar, se pueden usar conversiones implícitas o explícitas de otros valores constantes de tipo entero: const nint i = (nint)42; .Implicit or explicit casts of other integral constant values can be used instead: const nint i = (nint)42;.
nint las constantes están en el intervalo [ int.MinValue , int.MaxValue ].nint constants are in the range [ int.MinValue, int.MaxValue ].
nuint las constantes están en el intervalo [ uint.MinValue , uint.MaxValue ].nuint constants are in the range [ uint.MinValue, uint.MaxValue ].
No hay MinValue campos o MaxValue en nint o nuint porque, aparte de nuint.MinValue , esos valores no se pueden emitir como constantes.There are no MinValue or MaxValue fields on nint or nuint because, other than nuint.MinValue, those values cannot be emitted as constants.
Los operadores binarios {,,,,,, + - ~ + - ,, * / % == != < <= > >= & | ^ , << , >> ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, y.Constant folding is supported for all unary operators { +, -, ~ } and binary operators { +, -, *, /, %, ==, !=, <, <=, >, >=, &, |, ^, <<, >> }.
Las operaciones de plegamiento de constantes se evalúan con los Int32 UInt32 operandos y en lugar de los enteros nativos para un comportamiento coherente independientemente de la plataforma del compilador.Constant folding operations are evaluated with Int32 and UInt32 operands rather than native ints for consistent behavior regardless of compiler platform.
Si la operación da como resultado un valor constante en 32 bits, el plegamiento de constantes se realiza en tiempo de compilación.If the operation results in a constant value in 32-bits, constant folding is performed at compile-time.
De lo contrario, la operación se ejecuta en tiempo de ejecución y no se considera una constante.Otherwise the operation is executed at runtime and not considered a constant.
ConversionesConversions
Existe una conversión de identidad entre nint y IntPtr , y entre nuint y UIntPtr .There is an identity conversion between nint and IntPtr, and between nuint and UIntPtr.
Existe una conversión de identidad entre tipos compuestos que se diferencian solo en los tipos de ints nativos y los tipos subyacentes: matrices, Nullable<> , tipos construidos y tuplas.There is an identity conversion between compound types that differ by native ints and underlying types only: arrays, Nullable<>, constructed types, and tuples.
En las tablas siguientes se incluyen las conversiones entre los tipos especiales.The tables below cover the conversions between special types.
(El IL para cada conversión incluye las variantes para unchecked los checked contextos y si son diferentes).(The IL for each conversion includes the variants for unchecked and checked contexts if different.)
| OperandoOperand | DestinoTarget | ConversiónConversion | ILIL |
|---|---|---|---|
object |
nint |
UnboxingUnboxing | unbox |
void* |
nint |
PointerToVoidPointerToVoid | conv.i |
sbyte |
nint |
ImplicitNumericImplicitNumeric | conv.i |
byte |
nint |
ImplicitNumericImplicitNumeric | conv.u |
short |
nint |
ImplicitNumericImplicitNumeric | conv.i |
ushort |
nint |
ImplicitNumericImplicitNumeric | conv.u |
int |
nint |
ImplicitNumericImplicitNumeric | conv.i |
uint |
nint |
ExplicitNumericExplicitNumeric | conv.u / conv.ovf.u |
long |
nint |
ExplicitNumericExplicitNumeric | conv.i / conv.ovf.i |
ulong |
nint |
ExplicitNumericExplicitNumeric | conv.i / conv.ovf.i |
char |
nint |
ImplicitNumericImplicitNumeric | conv.i |
float |
nint |
ExplicitNumericExplicitNumeric | conv.i / conv.ovf.i |
double |
nint |
ExplicitNumericExplicitNumeric | conv.i / conv.ovf.i |
decimal |
nint |
ExplicitNumericExplicitNumeric | long decimal.op_Explicit(decimal) conv.i / ... conv.ovf.i |
IntPtr |
nint |
IdentidadIdentity | |
UIntPtr |
nint |
NingunoNone | |
object |
nuint |
UnboxingUnboxing | unbox |
void* |
nuint |
PointerToVoidPointerToVoid | conv.u |
sbyte |
nuint |
ExplicitNumericExplicitNumeric | conv.u / conv.ovf.u |
byte |
nuint |
ImplicitNumericImplicitNumeric | conv.u |
short |
nuint |
ExplicitNumericExplicitNumeric | conv.u / conv.ovf.u |
ushort |
nuint |
ImplicitNumericImplicitNumeric | conv.u |
int |
nuint |
ExplicitNumericExplicitNumeric | conv.u / conv.ovf.u |
uint |
nuint |
ImplicitNumericImplicitNumeric | conv.u |
long |
nuint |
ExplicitNumericExplicitNumeric | conv.u / conv.ovf.u |
ulong |
nuint |
ExplicitNumericExplicitNumeric | conv.u / conv.ovf.u |
char |
nuint |
ImplicitNumericImplicitNumeric | conv.u |
float |
nuint |
ExplicitNumericExplicitNumeric | conv.u / conv.ovf.u |
double |
nuint |
ExplicitNumericExplicitNumeric | conv.u / conv.ovf.u |
decimal |
nuint |
ExplicitNumericExplicitNumeric | ulong decimal.op_Explicit(decimal) conv.u / ... conv.ovf.u.un |
IntPtr |
nuint |
NingunoNone | |
UIntPtr |
nuint |
IdentidadIdentity | |
| EnumeraciónEnumeration | nint |
ExplicitEnumerationExplicitEnumeration | |
| EnumeraciónEnumeration | nuint |
ExplicitEnumerationExplicitEnumeration |
| OperandoOperand | DestinoTarget | ConversiónConversion | ILIL |
|---|---|---|---|
nint |
object |
BoxingBoxing | box |
nint |
void* |
PointerToVoidPointerToVoid | conv.i |
nint |
nuint |
ExplicitNumericExplicitNumeric | conv.u / conv.ovf.u |
nint |
sbyte |
ExplicitNumericExplicitNumeric | conv.i1 / conv.ovf.i1 |
nint |
byte |
ExplicitNumericExplicitNumeric | conv.u1 / conv.ovf.u1 |
nint |
short |
ExplicitNumericExplicitNumeric | conv.i2 / conv.ovf.i2 |
nint |
ushort |
ExplicitNumericExplicitNumeric | conv.u2 / conv.ovf.u2 |
nint |
int |
ExplicitNumericExplicitNumeric | conv.i4 / conv.ovf.i4 |
nint |
uint |
ExplicitNumericExplicitNumeric | conv.u4 / conv.ovf.u4 |
nint |
long |
ImplicitNumericImplicitNumeric | conv.i8 / conv.ovf.i8 |
nint |
ulong |
ExplicitNumericExplicitNumeric | conv.i8 / conv.ovf.i8 |
nint |
char |
ExplicitNumericExplicitNumeric | conv.u2 / conv.ovf.u2 |
nint |
float |
ImplicitNumericImplicitNumeric | conv.r4 |
nint |
double |
ImplicitNumericImplicitNumeric | conv.r8 |
nint |
decimal |
ImplicitNumericImplicitNumeric | conv.i8 decimal decimal.op_Implicit(long) |
nint |
IntPtr |
IdentidadIdentity | |
nint |
UIntPtr |
NingunoNone | |
nint |
EnumeraciónEnumeration | ExplicitEnumerationExplicitEnumeration | |
nuint |
object |
BoxingBoxing | box |
nuint |
void* |
PointerToVoidPointerToVoid | conv.u |
nuint |
nint |
ExplicitNumericExplicitNumeric | conv.i / conv.ovf.i |
nuint |
sbyte |
ExplicitNumericExplicitNumeric | conv.i1 / conv.ovf.i1 |
nuint |
byte |
ExplicitNumericExplicitNumeric | conv.u1 / conv.ovf.u1 |
nuint |
short |
ExplicitNumericExplicitNumeric | conv.i2 / conv.ovf.i2 |
nuint |
ushort |
ExplicitNumericExplicitNumeric | conv.u2 / conv.ovf.u2 |
nuint |
int |
ExplicitNumericExplicitNumeric | conv.i4 / conv.ovf.i4 |
nuint |
uint |
ExplicitNumericExplicitNumeric | conv.u4 / conv.ovf.u4 |
nuint |
long |
ExplicitNumericExplicitNumeric | conv.i8 / conv.ovf.i8 |
nuint |
ulong |
ImplicitNumericImplicitNumeric | conv.u8 / conv.ovf.u8 |
nuint |
char |
ExplicitNumericExplicitNumeric | conv.u2 / conv.ovf.u2.un |
nuint |
float |
ImplicitNumericImplicitNumeric | conv.r.un conv.r4 |
nuint |
double |
ImplicitNumericImplicitNumeric | conv.r.un conv.r8 |
nuint |
decimal |
ImplicitNumericImplicitNumeric | conv.u8 decimal decimal.op_Implicit(ulong) |
nuint |
IntPtr |
NingunoNone | |
nuint |
UIntPtr |
IdentidadIdentity | |
nuint |
EnumeraciónEnumeration | ExplicitEnumerationExplicitEnumeration |
La conversión de A a Nullable<B> es:Conversion from A to Nullable<B> is:
- una conversión implícita que acepta valores NULL si hay una conversión de identidad o implícita de
AaB;an implicit nullable conversion if there is an identity conversion or implicit conversion fromAtoB; - una conversión explícita que acepta valores NULL si hay una conversión explícita de
AaB;an explicit nullable conversion if there is an explicit conversion fromAtoB; - de lo contrario, no es válido.otherwise invalid.
La conversión de Nullable<A> a B es:Conversion from Nullable<A> to B is:
- una conversión explícita que acepta valores NULL si hay una conversión de identidad o una conversión numérica implícita o explícita de
AaB;an explicit nullable conversion if there is an identity conversion or implicit or explicit numeric conversion fromAtoB; - de lo contrario, no es válido.otherwise invalid.
La conversión de Nullable<A> a Nullable<B> es:Conversion from Nullable<A> to Nullable<B> is:
- una conversión de identidad si hay una conversión de identidad de
AaB;an identity conversion if there is an identity conversion fromAtoB; - una conversión explícita que acepta valores NULL si hay una conversión numérica implícita o explícita de
AaB;an explicit nullable conversion if there is an implicit or explicit numeric conversion fromAtoB; - de lo contrario, no es válido.otherwise invalid.
OperadoresOperators
Los operadores predefinidos son los siguientes.The predefined operators are as follows.
Estos operadores se tienen en cuenta durante la resolución de sobrecarga basada en reglas normales para las conversiones implícitas si al menos uno de los operandos es de tipo nint o nuint.These operators are considered during overload resolution based on normal rules for implicit conversions if at least one of the operands is of type nint or nuint.
(El IL para cada operador incluye las variantes para unchecked los checked contextos y si son diferentes).(The IL for each operator includes the variants for unchecked and checked contexts if different.)
| UnarioUnary | Firma del operadorOperator Signature | ILIL |
|---|---|---|
+ |
nint operator +(nint value) |
nop |
+ |
nuint operator +(nuint value) |
nop |
- |
nint operator -(nint value) |
neg |
~ |
nint operator ~(nint value) |
not |
~ |
nuint operator ~(nuint value) |
not |
| BinaryBinary | Firma del operadorOperator Signature | ILIL |
|---|---|---|
+ |
nint operator +(nint left, nint right) |
add / add.ovf |
+ |
nuint operator +(nuint left, nuint right) |
add / add.ovf.un |
- |
nint operator -(nint left, nint right) |
sub / sub.ovf |
- |
nuint operator -(nuint left, nuint right) |
sub / sub.ovf.un |
* |
nint operator *(nint left, nint right) |
mul / mul.ovf |
* |
nuint operator *(nuint left, nuint right) |
mul / mul.ovf.un |
/ |
nint operator /(nint left, nint right) |
div |
/ |
nuint operator /(nuint left, nuint right) |
div.un |
% |
nint operator %(nint left, nint right) |
rem |
% |
nuint operator %(nuint left, nuint right) |
rem.un |
== |
bool operator ==(nint left, nint right) |
beq / ceq |
== |
bool operator ==(nuint left, nuint right) |
beq / ceq |
!= |
bool operator !=(nint left, nint right) |
bne |
!= |
bool operator !=(nuint left, nuint right) |
bne |
< |
bool operator <(nint left, nint right) |
blt / clt |
< |
bool operator <(nuint left, nuint right) |
blt.un / clt.un |
<= |
bool operator <=(nint left, nint right) |
ble |
<= |
bool operator <=(nuint left, nuint right) |
ble.un |
> |
bool operator >(nint left, nint right) |
bgt / cgt |
> |
bool operator >(nuint left, nuint right) |
bgt.un / cgt.un |
>= |
bool operator >=(nint left, nint right) |
bge |
>= |
bool operator >=(nuint left, nuint right) |
bge.un |
& |
nint operator &(nint left, nint right) |
and |
& |
nuint operator &(nuint left, nuint right) |
and |
| |
nint operator |(nint left, nint right) |
or |
| |
nuint operator |(nuint left, nuint right) |
or |
^ |
nint operator ^(nint left, nint right) |
xor |
^ |
nuint operator ^(nuint left, nuint right) |
xor |
<< |
nint operator <<(nint left, int right) |
shl |
<< |
nuint operator <<(nuint left, int right) |
shl |
>> |
nint operator >>(nint left, int right) |
shr |
>> |
nuint operator >>(nuint left, int right) |
shr.un |
En algunos operadores binarios, los operadores de IL admiten tipos de operando adicionales (vea la tabla de tipos de operandos ECMA-335 III. 1.5).For some binary operators, the IL operators support additional operand types (see ECMA-335 III.1.5 Operand type table). Pero el conjunto de tipos de operando admitido por C# está limitado por simplicidad y coherencia con los operadores existentes en el lenguaje.But the set of operand types supported by C# is limited for simplicity and for consistency with existing operators in the language.
Se admiten las versiones de elevación de los operadores, donde los argumentos y los tipos devueltos son nint? y nuint? .Lifted versions of the operators, where the arguments and return types are nint? and nuint?, are supported.
Las operaciones de asignación compuesta x op= y donde x o y son enteros nativos siguen las mismas reglas que con otros tipos primitivos con operadores predefinidos.Compound assignment operations x op= y where x or y are native ints follow the same rules as with other primitive types with pre-defined operators.
En concreto, la expresión se enlaza como x = (T)(x op y) donde T es el tipo de x y donde x solo se evalúa una vez.Specifically the expression is bound as x = (T)(x op y) where T is the type of x and where x is only evaluated once.
Los operadores de desplazamiento deben enmascarar el número de bits para desplazarse a 5 bits si sizeof(nint) es 4 y a 6 bits si sizeof(nint) es 8.The shift operators should mask the number of bits to shift - to 5 bits if sizeof(nint) is 4, and to 6 bits if sizeof(nint) is 8.
(vea operadores de desplazamiento en la especificación de C#).(see shift operators in C# spec).
El compilador de C# 9 notificará los errores que se enlazan a los operadores de enteros nativos predefinidos al compilar con una versión de lenguaje anterior, pero permitirá el uso de conversiones predefinidas a y desde enteros nativos.The C#9 compiler will report errors binding to predefined native integer operators when compiling with an earlier language version, but will allow use of predefined conversions to and from native integers.
csc -langversion:9 -t:library A.cs
public class A
{
public static nint F;
}
csc -langversion:8 -r:A.dll B.cs
class B : A
{
static void Main()
{
F = F + 1; // error: nint operator+ not available with -langversion:8
F = (System.IntPtr)F + 1; // ok
}
}
DinámicaDynamic
El compilador sintetiza las conversiones y los operadores y no forman parte de los IntPtr tipos y subyacentes UIntPtr .The conversions and operators are synthesized by the compiler and are not part of the underlying IntPtr and UIntPtr types.
Como resultado, esas conversiones y operadores no están disponibles en el enlazador en tiempo de ejecución de dynamic .As a result those conversions and operators are not available from the runtime binder for dynamic.
nint x = 2;
nint y = x + x; // ok
dynamic d = x;
nint z = d + x; // RuntimeBinderException: '+' cannot be applied 'System.IntPtr' and 'System.IntPtr'
Miembros de tiposType members
El único constructor para nint o nuint es el constructor sin parámetros.The only constructor for nint or nuint is the parameter-less constructor.
Los siguientes miembros de System.IntPtr y System.UIntPtr se excluyen explícitamente de nint o nuint :The following members of System.IntPtr and System.UIntPtr are explicitly excluded from nint or nuint:
// constructors
// arithmetic operators
// implicit and explicit conversions
public static readonly IntPtr Zero; // use 0 instead
public static int Size { get; } // use sizeof() instead
public static IntPtr Add(IntPtr pointer, int offset);
public static IntPtr Subtract(IntPtr pointer, int offset);
public int ToInt32();
public long ToInt64();
public void* ToPointer();
Los miembros restantes de System.IntPtr y System.UIntPtr se incluyen implícitamente en nint y nuint .The remaining members of System.IntPtr and System.UIntPtr are implicitly included in nint and nuint. Por .NET Framework 4.7.2:For .NET Framework 4.7.2:
public override bool Equals(object obj);
public override int GetHashCode();
public override string ToString();
public string ToString(string format);
Las interfaces implementadas por System.IntPtr y System.UIntPtr se incluyen implícitamente en nint y nuint , con apariciones de los tipos subyacentes reemplazados por los tipos enteros nativos correspondientes.Interfaces implemented by System.IntPtr and System.UIntPtr are implicitly included in nint and nuint, with occurrences of the underlying types replaced by the corresponding native integer types.
Por ejemplo IntPtr , si implementa ISerializable, IEquatable<IntPtr>, IComparable<IntPtr> , nint implementa ISerializable, IEquatable<nint>, IComparable<nint> .For instance if IntPtr implements ISerializable, IEquatable<IntPtr>, IComparable<IntPtr>, then nint implements ISerializable, IEquatable<nint>, IComparable<nint>.
Reemplazar, ocultar e implementarOverriding, hiding, and implementing
nint y System.IntPtr , y nuint y System.UIntPtr , se consideran equivalentes para reemplazar, ocultar e implementar.nint and System.IntPtr, and nuint and System.UIntPtr, are considered equivalent for overriding, hiding, and implementing.
Las sobrecargas no pueden diferenciarse en nint and System.IntPtr , and nuint y System.UIntPtr , solos.Overloads cannot differ by nint and System.IntPtr, and nuint and System.UIntPtr, alone.
Las invalidaciones y las implementaciones pueden diferir en nint and System.IntPtr , or nuint y System.UIntPtr , solos.Overrides and implementations may differ by nint and System.IntPtr, or nuint and System.UIntPtr, alone.
Los métodos ocultan otros métodos que difieren por nint and System.IntPtr , or nuint y System.UIntPtr , solos.Methods hide other methods that differ by nint and System.IntPtr, or nuint and System.UIntPtr, alone.
VariosMiscellaneous
nint las nuint expresiones y utilizadas como índices de matriz se emiten sin conversión.nint and nuint expressions used as array indices are emitted without conversion.
static object GetItem(object[] array, nint index)
{
return array[index]; // ok
}
nint y nuint se pueden usar como un enum tipo base.nint and nuint can be used as an enum base type.
enum E : nint // ok
{
}
Las lecturas y escrituras son atómicas para los tipos nint , nuint y enum con el tipo base nint o nuint .Reads and writes are atomic for types nint, nuint, and enum with base type nint or nuint.
Los campos se pueden marcar volatile para tipos nint y nuint .Fields may be marked volatile for types nint and nuint.
ECMA-334 15.5.4 no incluye enum con el tipo base System.IntPtr o System.UIntPtr sin embargo.ECMA-334 15.5.4 does not include enum with base type System.IntPtr or System.UIntPtr however.
default(nint) y new nint() son equivalentes a (nint)0 .default(nint) and new nint() are equivalent to (nint)0.
typeof(nint) es typeof(IntPtr).typeof(nint) is typeof(IntPtr).
sizeof(nint) se admite pero requiere compilación en un contexto no seguro (como hace sizeof(IntPtr) ).sizeof(nint) is supported but requires compiling in an unsafe context (as does sizeof(IntPtr)).
El valor no es una constante de tiempo de compilación.The value is not a compile-time constant.
sizeof(nint) se implementa como sizeof(IntPtr) en lugar de IntPtr.Size .sizeof(nint) is implemented as sizeof(IntPtr) rather than IntPtr.Size.
Diagnóstico del compilador para referencias de tipo que implican nint o nuint notifican o nint nuint en lugar de IntPtr o UIntPtr .Compiler diagnostics for type references involving nint or nuint report nint or nuint rather than IntPtr or UIntPtr.
MetadatosMetadata
nint y nuint se representan en metadatos como System.IntPtr y System.UIntPtr .nint and nuint are represented in metadata as System.IntPtr and System.UIntPtr.
Las referencias de tipo que incluyen nint o nuint se emiten con System.Runtime.CompilerServices.NativeIntegerAttribute para indicar qué partes de la referencia de tipo son ints nativas.Type references that include nint or nuint are emitted with a System.Runtime.CompilerServices.NativeIntegerAttribute to indicate which parts of the type reference are native ints.
namespace System.Runtime.CompilerServices
{
[AttributeUsage(
AttributeTargets.Class |
AttributeTargets.Event |
AttributeTargets.Field |
AttributeTargets.GenericParameter |
AttributeTargets.Parameter |
AttributeTargets.Property |
AttributeTargets.ReturnValue,
AllowMultiple = false,
Inherited = false)]
public sealed class NativeIntegerAttribute : Attribute
{
public NativeIntegerAttribute()
{
TransformFlags = new[] { true };
}
public NativeIntegerAttribute(bool[] flags)
{
TransformFlags = flags;
}
public readonly bool[] TransformFlags;
}
}
La codificación de referencias de tipo con NativeIntegerAttribute se trata en NativeIntegerAttribute.MD.The encoding of type references with NativeIntegerAttribute is covered in NativeIntegerAttribute.md.
AlternativasAlternatives
Una alternativa al enfoque de "eliminación de tipos" anterior es introducir nuevos tipos: System.NativeInt y System.NativeUInt .An alternative to the "type erasure" approach above is to introduce new types: System.NativeInt and System.NativeUInt.
public readonly struct NativeInt
{
public IntPtr Value;
}
Los tipos DISTINCT permitiría la sobrecarga DISTINCT de IntPtr y permitiría el análisis distinto y ToString() .Distinct types would allow overloading distinct from IntPtr and would allow distinct parsing and ToString().
Pero sería más trabajo para que CLR controlara estos tipos de forma eficaz, lo que invalidaría el propósito principal de la eficacia de la característica.But there would be more work for the CLR to handle these types efficiently which defeats the primary purpose of the feature - efficiency.
Y la interoperabilidad con código INT nativo existente que utiliza IntPtr sería más difícil.And interop with existing native int code that uses IntPtr would be more difficult.
Otra alternativa consiste en agregar compatibilidad de tipo int más nativa para IntPtr en el marco de trabajo, pero sin ninguna compatibilidad de compilador específica.Another alternative is to add more native int support for IntPtr in the framework but without any specific compiler support.
El compilador admitirá automáticamente las nuevas conversiones y operaciones aritméticas.Any new conversions and arithmetic operations would be supported by the compiler automatically.
Pero el lenguaje no proporcionaría palabras clave, constantes u checked operaciones.But the language would not provide keywords, constants, or checked operations.
Design MeetingsDesign meetings
- https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-05-26.md
- https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-06-13.md
- https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-07-05.md#native-int-and-intptr-operators
- https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-10-23.md
- https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-03-25.md