¿Algún uso real de punteros en C #? [cerrado]

19

¿Cuál es una situación mientras se codifica en C # donde el uso de punteros es una buena o necesaria opción? Estoy hablando de punteros inseguros .

Gulshan
fuente
8
Ahhh hombre, vi la pregunta y me puse contento porque podía explicar que en C # usas punteros todo el tiempo, pero tenías que ir y arruinarlo diciendo explícitamente la palabra clave insegura. Dang it! :)
Tony

Respuestas:

25

Del desarrollador del propio C #:

El uso de punteros rara vez se requiere en C #, pero hay algunas situaciones que los requieren. Como ejemplos, el uso de un contexto inseguro para permitir punteros está garantizado por los siguientes casos:

  • Manejo de estructuras existentes en disco
  • Escenarios de COM avanzado o invocación de plataforma que involucran estructuras con punteros en ellos
  • Código de rendimiento crítico

Se desaconseja el uso de contextos inseguros en otras situaciones.

Específicamente, un contexto inseguro no debe usarse para intentar escribir código C en C #.

Precaución: "El código escrito utilizando un contexto inseguro no puede verificarse como seguro, por lo que se ejecutará solo cuando el código sea totalmente confiable. En otras palabras, el código inseguro no se puede ejecutar en un entorno no confiable. Por ejemplo, no puede ejecutar inseguro código directamente desde Internet ".

Puedes pasar por esto como referencia

ykombinator
fuente
"el código inseguro no se puede ejecutar en un entorno no confiable". ¿Quiso decir "de confianza"?
Don Larynx
18

Sí, hay usos reales, cuando el rendimiento es crítico y las operaciones son de bajo nivel.

por ejemplo, solo necesito usar punteros en C # una vez, para comparar imágenes. El uso de GetPixel en un par de imágenes de 1024x1024x32 tomó 2 minutos para hacer la comparación (coincidencia exacta). Fijar la memoria de imagen y usar punteros tomó menos de 1 segundo (en la misma máquina, por supuesto).

Steven A. Lowe
fuente
2
He usado LockBits para eso ... ( msdn.microsoft.com/en-us/library/… )
configurador
1
@configurator: esto era .net 2, LockBits no existía
Steven A. Lowe
2
Claro que sí, existía desde 1.0 ...
configurador
@configurator: mi error, me confundí al navegar por la documentación de MSDN (cuando cambié a .net 2 en la lista desplegable fue a una página completamente diferente que no mencionaba los bits de bloqueo). Sí, así es como se fija la memoria de la imagen.
Steven A. Lowe
6

Debe recordar que los diseñadores de Microsoft son personas inteligentes y todo lo que agregan a C # tiene al menos 1 caso de uso. El proyecto FParsec utiliza código inseguro para mostrar hasta la última caída de rendimiento que C # es capaz de hacer. Tome nota del uso de fixedy 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
fuente
1
Yo diría que los desarrolladores (en Microsoft o en cualquier otra compañía) serían un idiota si incluyeran alguna función porque tiene 1 caso de uso. Una característica debe tener mucho más que solo 1 caso de uso; de lo contrario es una hinchazón.
Lie Ryan
44
Raymond Chen ha dicho a menudo que las características en Microsoft comienzan en -100 "puntos". Para que una característica se implemente, "tiene que tener un efecto positivo neto significativo en el paquete general para que pueda entrar". Aquí está la publicación de blog de ericgu sobre este c.2004: blogs.msdn.com/b/ericgu/archive/2004/01/12/57985.aspx
Jesse Buchanan
Estoy bastante seguro de que algunas operaciones de String utilizan internamente código inseguro. Por lo tanto, FParsec puede no haber sido la prioridad.
Arturo Torres Sánchez
4

Una vez tuve que usar punteros (en el contexto inseguro) en una aplicación de Windows basada en C # que actuaría como una interfaz para un auricular. Esta aplicación es una interfaz de usuario que permitiría a los agentes (en un centro de llamadas) controlar la configuración de sus auriculares. Esta aplicación actúa como una alternativa al panel de control proporcionado por el fabricante del auricular. Por lo tanto, su capacidad para controlar los auriculares era limitada en comparación con las opciones disponibles. Tuve que usar punteros porque tuve que usar la API (un dll de Visual C ++) proporcionada por el fabricante de auriculares usando P / Invoke.

k25
fuente