Какова ситуация при кодировании в C #, где использование указателей является хорошим или необходимым вариантом? Я говорю о небезопасных указателях.
Какова ситуация при кодировании в C #, где использование указателей является хорошим или необходимым вариантом? Я говорю о небезопасных указателях.
Ответы:
От самого разработчика C #:
Использование указателей редко требуется в C #, но в некоторых ситуациях они требуются. Например, использование небезопасного контекста для разрешения указателей оправдано следующими случаями:
- Работа с существующими структурами на диске
- Сценарии Advanced COM или Platform Invoke, включающие структуры с указателями в них
- Код, критичный к производительности
Использование небезопасного контекста в других ситуациях не рекомендуется.
В частности, небезопасный контекст не должен использоваться для попытки написания C-кода на C #.
Предупреждение: «Код, написанный с использованием небезопасного контекста, не может быть проверен на безопасность, поэтому он будет выполняться только тогда, когда код является полностью доверенным. Другими словами, небезопасный код не может быть выполнен в ненадежной среде. Например, вы не можете запустить небезопасный код прямо из интернета. "
Вы можете пройти через это для справки
да, есть реальные применения, когда производительность критична, а операции находятся на низком уровне
Например, мне нужно было использовать указатели в C # только один раз, для сравнения изображений. Использование GetPixel для пары изображений размером 1024x1024x32 заняло 2 минуты для сравнения (точное совпадение). Закрепление памяти изображения и использование указателей заняло менее 1 секунды (конечно, на той же машине).
Вы должны помнить, что дизайнеры в 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;
}
}
}
Мне когда-то приходилось использовать указатели (в небезопасном контексте) в приложении Windows на основе C #, которое могло бы служить интерфейсом для гарнитуры. Это приложение представляет собой пользовательский интерфейс, который позволяет агентам (в колл-центре) управлять настройками наушников. Это приложение действует как альтернатива панели управления, предоставленной производителем гарнитуры. Таким образом, их способность управлять наушниками была ограничена по сравнению с доступными опциями. Мне пришлось использовать указатели, потому что я должен был использовать API (DLL Visual C ++), предоставляемый производителем гарнитуры с помощью P / Invoke.