Bagikan melalui


IntPtr Numerik

Nota

Artikel ini adalah spesifikasi fitur. Spesifikasi berfungsi sebagai dokumen desain untuk fitur tersebut. Ini termasuk perubahan spesifikasi yang diusulkan, bersama dengan informasi yang diperlukan selama desain dan pengembangan fitur. Artikel ini diterbitkan sampai perubahan spesifikasi yang diusulkan diselesaikan dan dimasukkan dalam spesifikasi ECMA saat ini.

Mungkin ada beberapa perbedaan antara spesifikasi fitur dan implementasi yang selesai. Perbedaan tersebut dituangkan dalam catatan rapat desain bahasa yang relevan.

Anda dapat mempelajari lebih lanjut tentang proses untuk mengadopsi speklet fitur ke dalam standar bahasa C# dalam artikel tentang spesifikasi .

Isu Juara: https://github.com/dotnet/csharplang/issues/6065

Ringkasan

Ini adalah revisi pada fitur awal bilangan bulat asli (spesifikasi), yang mana jenis nint/nuint berbeda dari jenis dasar System.IntPtr/System.UIntPtr. Singkatnya, kita sekarang memperlakukan nint/nuint sebagai jenis sederhana aliasing System.IntPtr/System.UIntPtr, seperti yang kita lakukan untuk int dalam kaitannya dengan System.Int32. Bendera fitur runtime System.Runtime.CompilerServices.RuntimeFeature.NumericIntPtr memicu perilaku baru ini.

Desain

8.3.5 Jenis sederhana

C# menyediakan sekumpulan jenis struct yang telah ditentukan sebelumnya yang disebut jenis sederhana. Jenis sederhana diidentifikasi melalui kata kunci, tetapi kata kunci ini hanyalah alias untuk jenis struct yang telah ditentukan sebelumnya di namespace System, seperti yang dijelaskan dalam tabel di bawah ini.

Kata Kunci jenis Alias
sbyte System.SByte
byte System.Byte
short System.Int16
ushort System.UInt16
int System.Int32
uint System.UInt32
nint System.IntPtr
nuint System.UIntPtr
long System.Int64
ulong System.UInt64
char System.Char
float System.Single
double System.Double
bool System.Boolean
decimal System.Decimal

[...]

8.3.6 Jenis integral

C# mendukung sebelas jenis integral: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, dan char. [...]

8.8 Jenis tidak terkelola

Dengan kata lain, unmanaged_type adalah salah satu dari yang berikut:

  • sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal, atau bool.
  • Setiap enum_type.
  • Setiap struct_type yang ditentukan pengguna yang bukan jenis yang diproduksi dan hanya berisi elemen-elemen unmanaged_type.
  • Dalam kode yang tidak aman, tipe pointer apa pun.

10.2.3 Konversi numerik implisit

Konversi numerik implisit adalah:

  • Dari sbyte ke short, int, nint, long, float, double, atau decimal.
  • Dari byte ke short, ushort, int, uint, nint, nuint, long, ulong, float, double, atau decimal.
  • Dari short ke int, nint, long, float, double, atau decimal.
  • Dari ushort ke int, uint, nint, nuint, long, ulong, float, double, atau decimal.
  • Dari int ke nint, long, float, double, atau decimal.
  • Dari uint ke nuint, long, ulong, float, double, atau decimal.
  • Dari nint ke long, float, double, atau decimal.
  • Dari nuint ke ulong, float, double, atau decimal.
  • Dari long ke float, double, atau decimal.
  • Dari ulong ke float, double, atau decimal.
  • Dari char ke ushort, int, uint, nint, nuint, long, ulong, float, double, atau decimal.
  • Dari float ke double.

[...]

10.2.11 Konversi ekspresi konstanta implisit

Konversi ekspresi konstanta implisit mengizinkan konversi berikut:

  • constant_expression jenis int dapat dikonversi ke jenis sbyte, byte, short, ushort, uint, nint, nuint, atau ulong, asalkan nilai constant_expression berada dalam rentang jenis tujuan. [...]

10.3.2 Konversi numerik eksplisit

Konversi numerik eksplisit adalah konversi dari numeric_type ke numeric_type lain yang konversi numerik implisitnya belum ada:

  • Dari sbyte ke byte, ushort, uint, nuint, ulong, atau char.
  • Dari byte ke sbyte atau char.
  • Dari short ke sbyte, byte, ushort, uint, nuint, ulong, atau char.
  • Dari ushort ke sbyte, byte, short, atau char.
  • Dari int ke sbyte, byte, short, ushort, uint, nuint, ulong, atau char.
  • Dari uint ke sbyte, byte, short, ushort, int, nint, atau char.
  • Dari long ke sbyte, byte, short, ushort, int, uint, nint, nuint, ulong, atau char.
  • Dari nint ke sbyte, byte, short, ushort, int, uint, nuint, ulong, atau char.
  • Dari nuint ke sbyte, byte, short, ushort, int, uint, nint, long, atau char.
  • Dari ulong ke sbyte, byte, short, ushort, int, uint, nint, nuint, long, atau char.
  • Dari char ke sbyte, byte, atau short.
  • Dari float ke sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, atau decimal.
  • Dari double ke sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, atau decimal.
  • Dari decimal ke sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, atau double.

[...]

10.3.3 Konversi enumerasi eksplisit

Konversi enumerasi eksplisit terdiri dari:

  • Dari sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, atau decimal ke enum_typeapa pun .
  • Dari setiap enum_type hingga sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, atau decimal.
  • Dari setiap enum_type ke enum_typelainnya.

12.6.4.7 Target konversi yang lebih baik

Mengingat dua jenis T₁ dan T₂, T₁ adalah target konversi yang lebih baik daripada T₂ jika salah satu dari yang berikut ini berlaku:

  • Konversi implisit dari T₁ ke T₂ ada dan tidak ada konversi implisit dari T₂ ke T₁ ada
  • T₁ Task<S₁>, T₂Task<S₂>, dan S₁ adalah target konversi yang lebih baik daripada S₂
  • T₁ S₁ atau S₁? di mana S₁ adalah jenis integral yang ditandatangani, dan T₂S₂ atau S₂? di mana S₂ adalah jenis integral yang tidak ditandatangani. Secara khusus: [...]

12.8.12 Akses elemen

[...] Jumlah ekspresi dalam argument_list harus sama dengan peringkat array_type, dan setiap ekspresi harus berjenis int, uint, nint, nuint, long, atau ulong, atau akan secara implisit dapat dikonversi ke satu atau beberapa jenis ini.

11.8.12.2 Akses array

[...] Jumlah ekspresi dalam argument_list harus sama dengan peringkat array_type, dan setiap ekspresi harus berjenis int, uint, nint, nuint, long, atau ulong, atau akan secara implisit dapat dikonversi ke satu atau beberapa jenis ini.

[...] Pemrosesan runtime pada akses array dengan format P[A], di mana P adalah primary_no_array_creation_expression dari tipe array_type dan A adalah argument_list, dilakukan dengan langkah-langkah berikut: [...]

  • Ekspresi indeks argument_list dievaluasi secara berurutan, dari kiri ke kanan. Setelah evaluasi setiap ekspresi indeks, konversi implisit ke salah satu jenis berikut dilakukan: int, uint, nint, nuint, long, ulong. Jenis pertama dalam daftar ini yang memiliki konversi implisit akan dipilih. [...]

12.8.16 Operator peningkatan dan penurunan Postfix

Resolusi kelebihan beban operator unary diterapkan untuk memilih implementasi operator tertentu. Operator ++ dan -- yang telah ditentukan sebelumnya ada untuk jenis berikut: sbyte, byte, short, ushort, int, uint, nint, nuint,long, ulong, char, float, double, decimal, dan jenis enum apa pun.

12.9.2 Operator unary plus

Operator unary plus yang telah ditentukan sebelumnya adalah:

...
nint operator +(nint x);
nuint operator +(nuint x);

12.9.3 Operator minus unari

Operator minus unari yang telah ditetapkan sebelumnya adalah:

  • Negasi bilangan bulat:

    ...
    nint operator –(nint x);
    

12.8.16 Operator peningkatan dan penurunan Postfix

Operator ++ dan -- yang telah ditentukan sebelumnya ada untuk jenis berikut: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal, dan jenis enum apa pun.

11.7.19 Ekspresi nilai default

Selain itu, default_value_expression adalah ekspresi konstanta jika jenisnya adalah salah satu jenis nilai berikut: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal, bool, atau jenis enumerasi apa pun.

12.9.5 Operator pelengkap Bitwise

Operator pelengkap bitwise yang telah ditentukan sebelumnya adalah:

...
nint operator ~(nint x);
nuint operator ~(nuint x);

12.9.6 Operator prefiks peningkatan dan penurunan

Operator ++ dan -- yang telah ditentukan sebelumnya ada untuk jenis berikut: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal, dan jenis enum apa pun.

12.10 Operator aritmatika

12.10.2 Operator perkalian

Operator perkalian yang telah ditentukan sebelumnya tercantum di bawah ini. Semua operator menghitung hasil kali dari x dan y.

  • Perkalian bilangan bulat:

    ...
    nint operator *(nint x, nint y);
    nuint operator *(nuint x, nuint y);
    

12.10.3 Operator pembagian

Operator divisi yang telah ditentukan sebelumnya tercantum di bawah ini. Semua operator tersebut menghitung hasil bagi dari x dan y.

  • Pembagian bilangan bulat:

    ...
    nint operator /(nint x, nint y);
    nuint operator /(nuint x, nuint y);
    

12.10.4 Operator sisa

Operator sisa yang telah ditentukan sebelumnya tercantum di bawah ini. Semua operator menghitung sisa pembagian antara x dan y.

  • Sisa bilangan bulat:

    ...
    nint operator %(nint x, nint y);
    nuint operator %(nuint x, nuint y);
    

12.10.5 Operator penambahan

  • Penambahan bilangan bulat:

    ...
    nint operator +(nint x, nint y);
    nuint operator +(nuint x, nuint y);
    

12.10.6 Operator pengurangan

  • Pengurangan bilangan bulat:

    ...
    nint operator –(nint x, nint y);
    nuint operator –(nuint x, nuint y);
    

12.11 Operator Shift

Operator shift yang telah ditentukan sebelumnya tercantum di bawah ini.

  • Geser ke kiri:

    ...
    nint operator <<(nint x, int count);
    nuint operator <<(nuint x, int count);
    
  • Geser ke kanan:

    ...
    nint operator >>(nint x, int count);
    nuint operator >>(nuint x, int count);
    

    Operator >> menggeser x ke kanan oleh sejumlah bit yang dihitung sebagaimana dijelaskan di bawah ini.

    Ketika x berjenis int, nint atau long, bit berurutan rendah x dibuang, bit yang tersisa digeser ke kanan, dan posisi bit kosong berurutan tinggi diatur ke nol jika x tidak negatif dan diatur ke satu jika x negatif.

    Ketika x berjenis uint, nuint atau ulong, bit urutan rendah x dibuang, bit yang tersisa digeser ke kanan, dan posisi bit kosong urutan tinggi diatur ke nol.

  • Pergeseran tanpa tanda ke kanan

    ...
    nint operator >>>(nint x, int count);
    nuint operator >>>(nuint x, int count);
    

Untuk operator yang telah ditentukan sebelumnya, jumlah bit yang akan digeser dihitung sebagai berikut: [...]

  • Ketika jenis x adalah nint atau nuint, jumlah pergeseran diberikan oleh lima bit urutan terendah dari count pada platform 32-bit, atau enam bit urutan terendah dari count pada platform 64-bit.

12.12 Operator relasional dan pengujian jenis

12.12.2 Operator perbandingan bilangan bulat

Operator perbandingan bilangan bulat yang telah ditentukan sebelumnya adalah:

...
bool operator ==(nint x, nint y);
bool operator ==(nuint x, nuint y);

bool operator !=(nint x, nint y);
bool operator !=(nuint x, nuint y);

bool operator <(nint x, nint y);
bool operator <(nuint x, nuint y);

bool operator >(nint x, nint y);
bool operator >(nuint x, nuint y);

bool operator <=(nint x, nint y);
bool operator <=(nuint x, nuint y);

bool operator >=(nint x, nint y);
bool operator >=(nuint x, nuint y);

12.12 Operator logis

12.12.2 Operator logis bilangan bulat

Operator logika bilangan bulat yang telah ditentukan sebelumnya adalah:

...
nint operator &(nint x, nint y);
nuint operator &(nuint x, nuint y);

nint operator |(nint x, nint y);
nuint operator |(nuint x, nuint y);

nint operator ^(nint x, nint y);
nuint operator ^(nuint x, nuint y);

12.22 Ekspresi konstanta

Ekspresi konstanta mungkin berupa jenis nilai atau jenis referensi. Jika ekspresi konstanta adalah jenis nilai, ekspresi harus merupakan salah satu jenis berikut: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal, bool, atau jenis enumerasi apa pun.

[...]

Konversi ekspresi konstan implisit memungkinkan ekspresi konstan jenis int dikonversi ke sbyte, byte, short, ushort, uint, nint, nuint, atau ulong, asalkan nilai ekspresi konstanta berada dalam rentang jenis tujuan.

17.4 Akses elemen Array

Elemen array diakses menggunakan ekspresi element_access bentuk A[I₁, I₂, ..., Iₓ], di mana A adalah ekspresi dari jenis array dan setiap Iₑ adalah ekspresi dari jenis int, uint, nint, nuint,long, ulong, atau dapat dikonversi secara implisit ke satu atau lebih dari jenis ini. Hasil dari akses elemen array adalah variabel, yaitu elemen array yang dipilih oleh indeks.

23.5 Konversi penunjuk

23.5.1 Umum

[...]

Selain itu, dalam konteks yang tidak aman, kumpulan konversi eksplisit yang tersedia diperluas untuk menyertakan konversi pointer eksplisit berikut:

  • Dari pointer_type apa pun ke pointer_typelainnya .
  • Dari sbyte, byte, short, ushort, int, uint, nint, nuint,long, atau ulong ke pointer_typeapa pun .
  • Dari pointer_type apa pun hingga sbyte, byte, short, ushort, int, uint, nint, nuint,long, atau ulong.

23.6.4 Akses elemen Pointer

[...] Dalam akses elemen penunjuk dari formulir P[E], P harus berupa ekspresi jenis penunjuk selain void*, dan E harus menjadi ekspresi yang dapat dikonversi secara implisit ke int, uint, nint, nuint,long, atau ulong.

23.6.7 Aritmatika pointer

Dalam konteks tidak aman, operator + dan operator dapat diterapkan ke nilai semua jenis pointer kecuali void*. Dengan demikian, untuk setiap jenis pointer T*, operator berikut secara implisit ditentukan:

[...]
T* operator +(T* x, nint y);
T* operator +(T* x, nuint y);
T* operator +(nint x, T* y);
T* operator +(nuint x, T* y);
T* operator -(T* x, nint y);
T* operator -(T* x, nuint y);

Mengingat ekspresi P dari tipe penunjuk T* dan ekspresi N dari tipe int, uint, nint, nuint,long, atau ulong, ekspresi P + N dan N + P menghitung nilai penunjuk dari jenis T* yang dihasilkan dari menambahkan N * sizeof(T) ke alamat yang diberikan oleh P. Demikian juga, ekspresi P – N menghitung nilai penunjuk jenis T* yang dihasilkan dari pengurangan N * sizeof(T) dari alamat yang diberikan oleh P.

Berbagai pertimbangan

Memutus perubahan

Salah satu dampak utama dari desain ini adalah bahwa System.IntPtr dan System.UIntPtr mendapatkan beberapa operator bawaan (konversi, unary dan biner).
Ini termasuk operator checked, artinya operator berikut pada jenis tersebut sekarang akan menghasilkan error saat terjadi kelebihan muatan:

  • IntPtr + int
  • IntPtr - int
  • IntPtr -> int
  • long -> IntPtr
  • void* -> IntPtr

Enkode metadata

Desain ini berarti bahwa nint dan nuint hanya dapat dipancarkan sebagai System.IntPtr dan System.UIntPtr, tanpa menggunakan System.Runtime.CompilerServices.NativeIntegerAttribute.
Demikian pula, saat memuat metadata NativeIntegerAttribute dapat diabaikan.