Есть ли реальное использование указателей в C #? [закрыто]

19

Какова ситуация при кодировании в C #, где использование указателей является хорошим или необходимым вариантом? Я говорю о небезопасных указателях.

Gulshan
источник
8
Аааа, чувак, я видел вопрос и был счастлив, потому что мне нужно было объяснить, что в C # вы все время используете указатели, но вам пришлось пойти и испортить это, явно сказав ключевое слово unsafe. Черт возьми! :)
Тони

Ответы:

25

От самого разработчика C #:

Использование указателей редко требуется в C #, но в некоторых ситуациях они требуются. Например, использование небезопасного контекста для разрешения указателей оправдано следующими случаями:

  • Работа с существующими структурами на диске
  • Сценарии Advanced COM или Platform Invoke, включающие структуры с указателями в них
  • Код, критичный к производительности

Использование небезопасного контекста в других ситуациях не рекомендуется.

В частности, небезопасный контекст не должен использоваться для попытки написания C-кода на C #.

Предупреждение: «Код, написанный с использованием небезопасного контекста, не может быть проверен на безопасность, поэтому он будет выполняться только тогда, когда код является полностью доверенным. Другими словами, небезопасный код не может быть выполнен в ненадежной среде. Например, вы не можете запустить небезопасный код прямо из интернета. "

Вы можете пройти через это для справки

ykombinator
источник
«небезопасный код не может быть выполнен в ненадежной среде». Вы имели в виду "доверенный"?
Дон Ларинкс
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;
        }
    }
}
ChaosPandion
источник
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 (DLL Visual C ++), предоставляемый производителем гарнитуры с помощью P / Invoke.

k25
источник