Будь-яке реальне використання покажчиків у C #? [зачинено]


19

Яка ситуація під час кодування в C #, де використання покажчиків є хорошим або необхідним варіантом? Я говорю про небезпечні покажчики.


8
А-а-а-а, людина, я побачила це питання і зраділа всіх задоволених, тому що я могла б пояснити, що в C # ви весь час використовуєте покажчики, але вам потрібно було піти і погубити це, чітко вимовляючи небезпечне ключове слово. Пограв! :)
Тоні

Відповіді:


25

Від самого розробника C #:

Використання покажчиків рідко потрібно в C #, але є деякі ситуації, які вимагають їх. Як приклад, використання небезпечного контексту для дозволу покажчиків гарантується такими випадками:

  • Робота з існуючими структурами на диску
  • Розширені сценарії COM або Platform Invoke, що передбачають структури з покажчиками в них
  • Критичний до продуктивності код

Використання небезпечного контексту в інших ситуаціях не рекомендується.

Зокрема, небезпечний контекст не повинен використовуватися для спроби запису коду С у C #.

Застереження: "Код, написаний з використанням небезпечного контексту, не може бути перевірений як безпечний, тому він буде виконуватися лише тоді, коли коду буде повністю довірено. Іншими словами, небезпечний код не може бути виконаний у ненадійному середовищі. Наприклад, ви не можете запустити небезпечний код безпосередньо з Інтернету. "

Ви можете переглядати це для довідки


"небезпечний код не може бути виконаний у ненадійному середовищі." Ви мали на увазі "довірений"?
Дон Ларінкс

18

так, є реальні можливості, коли продуктивність є критичною, а операції - низькими

наприклад, мені потрібно було лише один раз використовувати вказівники на C # для порівняння зображень. Використання GetPixel на парі 1024x1024x32 зображень знадобилося 2 хвилини для порівняння (Точне відповідність). Закріплення пам'яті зображення та використання покажчиків зайняло менше 1 секунди (звичайно, на тій же машині).


2
Я використовував LockBits для цього ... ( msdn.microsoft.com/en-us/library/… )
конфігуратор

1
@configurator: це було .net 2, LockBits не існувало
Стівен А. Лоу

2
Звичайно, це було з 1.0 ...
конфігуратор

@configurator: моя помилка, я заплутався в навігації по документації MSDN (коли я змінив на .net 2 у списку, що перейшов, він перейшов на зовсім іншу сторінку, яка не згадувала про блоки). Так, саме так ви закріплюєте пам'ять зображення.
Стівен А. Лоу

6

Ви повинні пам’ятати, що дизайнери Microsoft - це розумні люди, і все, що вони додають до C #, має принаймні 1 кейс використання. Проект FParsec використовує небезпечний код для виявлення кожної останньої краплі продуктивності, на яку здатний C #. Зверніть увагу на використання fixedта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
Я б сказав, що розробники (в Microsoft чи будь-яких інших компаніях) були б ідіотів, якби вони включили якусь функцію, оскільки вона має 1 випадок використання. Функція повинна мати набагато більше, ніж лише 1 випадки використання; інакше це набряк.
Лежи Райан

4
Реймонд Чен часто говорив, що функції у Microsoft починаються з -100 "балів". Для того, щоб функція була реалізована, вона "повинна мати суттєвий чистий позитивний ефект на загальний пакет для її введення". Ось запис в блозі ericgu про це c.2004: blogs.msdn.com/b/ericgu/archive/2004/01/12/57985.aspx
Джессі

Я впевнений, що деякі операції String внутрішньо використовують небезпечний код. Отже, FParsec, можливо, не був пріоритетним.
Артуро Торрес Санчес

4

Мені колись доводилося використовувати вказівники (в небезпечному контексті) в додатку Windows на основі C #, який буде виконувати функції інтерфейсу для гарнітури. Ця програма - це інтерфейс користувача, який дозволить агентам (у кол-центрі) контролювати свої настройки навушників. Ця програма виконує функції альтернативи панелі керування, яку надає виробник гарнітури. Таким чином, їхня можливість керувати гарнітурами була обмежена порівняно з наявними опціями. Мені довелося використовувати вказівники, тому що мені довелося використовувати API (Visual C ++ dll), наданий виробником гарнітури за допомогою P / Invoke.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.