C # işaretçiler herhangi bir gerçek kullanımı? [kapalı]


19

İşaretçileri kullanmanın iyi veya gerekli bir seçenek olduğu C # 'da kodlarken durum nedir? Güvensiz işaretçilerden bahsediyorum .


8
Ahhh adam, soruyu gördüm ve mutlu oldum çünkü C # 'da her zaman işaretçiler kullandığınızı açıklayacağım, ancak güvenli olmayan anahtar kelimeyi açıkça söyleyerek bunu mahvetmek zorunda kaldınız. Lanet olsun! :)
Tony

Yanıtlar:


25

C # geliştiricisinin kendisinden:

C # 'da işaretçilerin kullanımı nadiren gereklidir, ancak bunları gerektiren bazı durumlar vardır. Örnek olarak, işaretleyicilere izin vermek için güvenli olmayan bir bağlam kullanmak aşağıdaki durumlarda garanti edilir:

  • Diskteki mevcut yapılarla başa çıkmak
  • Gelişmiş COM veya Platform İşaretçileri olan yapıları içeren senaryoları çağırın
  • Performans açısından kritik kod

Güvenli olmayan bağlamın başka durumlarda kullanılması önerilmez.

Özellikle, C # 'da C kodu yazmaya çalışmak için güvenli olmayan bir bağlam kullanılmamalıdır.

Dikkat: "Güvenli olmayan bir bağlam kullanılarak yazılan kodun güvenli olduğu doğrulanamaz, bu nedenle yalnızca kod tam olarak güvenilir olduğunda çalıştırılır. Başka bir deyişle, güvenli olmayan kod güvenilir olmayan bir ortamda yürütülemez. Örneğin kodunu doğrudan İnternet'ten girin. "

Sen geçebilir bu başvuru için


"güvenli olmayan kod güvenilmeyen bir ortamda yürütülemez." Şunu mu demek istediniz: "güvenilir"?
Don Larynx

18

evet, performans kritik olduğunda ve işlemler düşük seviyedeyse gerçek kullanımlar vardır

Örneğin, görüntü karşılaştırma için yalnızca bir kez C # işaretçileri kullanmak gerekiyor. Bir çift 1024x1024x32 görüntü üzerinde GetPixel kullanmak karşılaştırmayı yapmak için 2 dakika sürdü (Tam eşleme). Görüntü belleğinin sabitlenmesi ve işaretçilerin kullanılması 1 saniyeden daha az sürdü (elbette aynı makinede).


2
Bunun için LockBits kullandınız ... ( msdn.microsoft.com/en-us/library/… )
yapılandırıcı

1
@configurator: Bu .net 2 idi, LockBits yoktu
Steven A. Lowe

2
Elbette, 1.0'dan beri var oldu ...
yapılandırıcı

@configurator: benim hatam, MSDN belgelerinde gezinme karıştı (açılan listede .net 2 olarak değiştirdiğimde, kilit bitlerinden bahsetmeyen tamamen farklı bir sayfaya gitti). Evet, görüntü belleğini bu şekilde sabitlersiniz.
Steven A. Lowe

6

Microsoft tasarımcılarının akıllı insanlar olduğunu ve C # 'a ekledikleri her şeyin en az 1 kullanım durumu olduğunu hatırlamanız gerekir. FParsec projesi C # yeteneğine sahip olduğunu performansın son damlasına ortaya çıkarmak için güvensiz kod kullanır. Kullanımının Duyurulur fixedve 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;
        }
    }
}

1
Geliştiricilerin (Microsoft'ta veya başka herhangi bir şirkette), bazı kullanım özellikleri içerdikleri için bir aptal olacağını söyleyebilirim çünkü 1 kullanım durumu var. Bir özellik yalnızca 1 kullanım durumundan daha fazlasına sahip olmalıdır; aksi takdirde bir şişkinliktir.
Yalan Ryan

4
Raymond Chen sıklıkla Microsoft'taki özelliklerin -100 "noktadan" başladığını söyledi. Bir özelliğin uygulanabilmesi için, "genel paketin bunu yapabilmesi için net bir net pozitif etkiye sahip olması gerekir". İşte bu c.2004 hakkında ericgu tarafından yazılmış blog yazısı: blogs.msdn.com/b/ericgu/archive/2004/01/12/57985.aspx
Jesse Buchanan

Eminim bazı String işlemleri dahili olarak güvensiz kod kullanır. Dolayısıyla, FParsec öncelikli olmayabilir.
Arturo Torres Sánchez

4

Bir kez bir kulaklık arabirimi olarak hareket C # tabanlı bir windows uygulamasında işaretçiler (güvenli olmayan bağlamda) kullanmak zorunda kaldı. Bu uygulama, ajanların (çağrı merkezinde) kulaklık ayarlarını kontrol etmesine izin veren bir kullanıcı arayüzüdür. Bu uygulama, kulaklık üreticisi tarafından verilen kontrol paneline alternatif olarak işlev görür. Böylece, kulaklıkları kontrol etme yetenekleri mevcut seçeneklerle karşılaştırıldığında sınırlıydı. P / Invoke kullanarak kulaklık üreticisi tarafından sağlanan API (bir Visual C ++ dll) kullanmak zorunda çünkü işaretçiler kullanmak zorunda kaldı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.