Adakah penggunaan nyata pointer dalam C #? [Tutup]

19

Apa situasi saat coding di C # di mana menggunakan pointer adalah pilihan yang baik atau perlu? Saya sedang berbicara tentang petunjuk yang tidak aman .

Gulshan
sumber
8
Ahhh, saya melihat pertanyaan itu dan merasa senang karena saya akan menjelaskan bahwa dalam C # Anda menggunakan pointer sepanjang waktu tetapi Anda harus pergi dan merusaknya dengan secara eksplisit mengatakan kata kunci yang tidak aman. Sial! :)
Tony

Jawaban:

25

Dari pengembang C # sendiri:

Penggunaan pointer jarang diperlukan dalam C #, tetapi ada beberapa situasi yang membutuhkannya. Sebagai contoh, menggunakan konteks yang tidak aman untuk memungkinkan pointer dijamin oleh kasus-kasus berikut:

  • Berurusan dengan struktur yang ada pada disk
  • Skenario Advanced COM atau Platform Invoke yang melibatkan struktur dengan pointer di dalamnya
  • Kode kritis kinerja

Penggunaan konteks yang tidak aman dalam situasi lain tidak disarankan.

Secara khusus, konteks yang tidak aman tidak boleh digunakan untuk mencoba menulis kode C dalam C #.

Perhatian: "Kode yang ditulis menggunakan konteks yang tidak aman tidak dapat diverifikasi untuk menjadi aman, sehingga hanya akan dieksekusi ketika kode tersebut sepenuhnya dipercaya. Dengan kata lain, kode yang tidak aman tidak dapat dieksekusi di lingkungan yang tidak terpercaya. Misalnya, Anda tidak dapat menjalankan yang tidak aman kode langsung dari Internet. "

Anda dapat membaca ini untuk referensi

ykombinator
sumber
"kode tidak aman tidak dapat dieksekusi di lingkungan yang tidak dipercaya." Apakah maksud Anda "tepercaya"?
Don Larynx
18

ya, ada kegunaan nyata, ketika kinerja sangat penting dan operasi tingkat rendah

misalnya, saya hanya perlu menggunakan pointer di C # sekali, untuk perbandingan gambar. Menggunakan GetPixel pada sepasang gambar 1024x1024x32 butuh waktu 2 menit untuk melakukan perbandingan (Pencocokan tepat). Menjepit memori gambar dan menggunakan pointer membutuhkan waktu kurang dari 1 detik (pada mesin yang sama tentunya).

Steven A. Lowe
sumber
2
Saya minta Anda menggunakan LockBits untuk itu ... ( msdn.microsoft.com/en-us/library/… )
konfigurator
1
@configurator: ini .net 2, LockBits tidak ada
Steven A. Lowe
2
Tentu saja, itu ada sejak 1.0 ...
konfigurator
@configurator: kesalahan saya, saya bingung menavigasi dokumentasi MSDN (ketika saya mengubah ke .net 2 di droplist, ia pergi ke halaman yang sama sekali berbeda yang tidak menyebutkan lockbits). Ya, itulah bagaimana Anda menyematkan memori gambar.
Steven A. Lowe
6

Anda harus ingat bahwa perancang di Microsoft adalah orang pintar dan semua yang mereka tambahkan ke C # memiliki setidaknya 1 kasing. Proyek FParsec menggunakan kode yang tidak aman untuk mengeluarkan setiap tetes kinerja terakhir yang mampu dilakukan oleh C #. Perhatikan penggunaan fixeddan stackalloc.

private char* ReadCharsFromStream(char* buffer, int maxCount, out string overhangChars) {
    Debug.Assert(maxCount >= 0);
    fixed (byte* byteBuffer = ByteBuffer) {
        overhangChars = null;
        try {
            while (maxCount >= MaxCharCountForOneByte) {// if maxCount < MaxCharCountForOneByte, Convert could throw
                int nBytesInByteBuffer = FillByteBuffer();
                bool flush = nBytesInByteBuffer == 0;
                int bytesUsed, charsUsed; bool completed = false;
                Decoder.Convert(byteBuffer + ByteBufferIndex, nBytesInByteBuffer,
                                buffer, maxCount, flush,
                                out bytesUsed, out charsUsed, out completed);
                ByteBufferIndex += bytesUsed; // GetChars consumed bytesUsed bytes from the byte buffer
                buffer += charsUsed;
                maxCount -= charsUsed;
                if (flush && completed) return buffer;
            }
            if (maxCount == 0) return buffer;

            char* cs = stackalloc char[MaxCharCountForOneByte];
            for (;;) {
                int nBytesInByteBuffer = FillByteBuffer();
                bool flush = nBytesInByteBuffer == 0;
                int bytesUsed, charsUsed; bool completed;
                Decoder.Convert(byteBuffer + ByteBufferIndex, nBytesInByteBuffer,
                                cs, MaxCharCountForOneByte, flush,
                                out bytesUsed, out charsUsed, out completed);
                ByteBufferIndex += bytesUsed;
                if (charsUsed > 0) {
                    int i = 0;
                    do {
                        *(buffer++) = cs[i++];
                        if (--maxCount == 0) {
                            if (i < charsUsed) overhangChars = new string(cs, i, charsUsed - i);
                            return buffer;
                        }
                    } while (i < charsUsed);
                }
                if (flush && completed) return buffer;
            }
        } catch (DecoderFallbackException e) {
            e.Data.Add("Stream.Position", ByteIndex + e.Index);
            throw;
        }
    }
}
Kekacauan Kekacauan
sumber
1
Saya akan mengatakan para pengembang (di Microsoft atau perusahaan lain) akan menjadi idiot jika mereka menyertakan beberapa fitur karena memiliki 1 use case. Fitur harus memiliki lebih dari 1 kasus penggunaan saja; kalau tidak, itu adalah mengasapi.
Lie Ryan
4
Raymond Chen sering mengatakan bahwa fitur di Microsoft mulai dari -100 "poin". Agar suatu fitur dapat diimplementasikan, ia "harus memiliki efek positif bersih yang signifikan pada keseluruhan paket untuk membuatnya masuk". Berikut posting blog ericgu tentang c.2004 ini: blogs.msdn.com/b/ericgu/archive/2004/01/12/57985.aspx
Jesse Buchanan
Saya cukup yakin beberapa operasi String secara internal menggunakan kode yang tidak aman. Jadi, FParsec mungkin bukan prioritas.
Arturo Torres Sánchez
4

Saya pernah harus menggunakan pointer (dalam konteks yang tidak aman) dalam aplikasi windows berbasis C # yang akan bertindak sebagai antarmuka ke headset. Aplikasi ini adalah antarmuka pengguna yang memungkinkan agen (di pusat panggilan) untuk mengontrol pengaturan headphone mereka. Aplikasi ini bertindak sebagai pengganti panel kontrol yang diberikan oleh produsen headset. Dengan demikian, kemampuan mereka untuk mengontrol headset terbatas jika dibandingkan dengan opsi yang tersedia. Saya harus menggunakan pointer karena saya harus menggunakan API (Visual C ++ dll) yang disediakan oleh produsen headset menggunakan P / Invoke.

k25
sumber