Algum uso real de ponteiros em C #? [fechadas]

19

O que é uma situação ao codificar em C # em que o uso de ponteiros é uma opção boa ou necessária? Estou falando de indicadores inseguros .

Gulshan
fonte
8
Ahhh, cara, eu vi a pergunta e fiquei feliz porque eu explicaria que em C # você usa ponteiros o tempo todo, mas você precisa arruinar isso dizendo explicitamente a palavra-chave insegura. Que droga! :)
Tony

Respostas:

25

Do desenvolvedor do próprio C #:

O uso de ponteiros raramente é necessário em C #, mas há algumas situações que os exigem. Como exemplos, o uso de um contexto não seguro para permitir ponteiros é garantido pelos seguintes casos:

  • Lidando com estruturas existentes no disco
  • Cenários avançados de COM ou Platform Invoke que envolvem estruturas com ponteiros neles
  • Código crítico de desempenho

O uso de contexto inseguro em outras situações é desencorajado.

Especificamente, um contexto não seguro não deve ser usado para tentar escrever código C em C #.

Cuidado: "O código gravado usando um contexto não seguro não pode ser verificado como seguro; portanto, ele será executado apenas quando o código for totalmente confiável. Em outras palavras, o código não seguro não poderá ser executado em um ambiente não confiável. Por exemplo, você não pode executar não seguro. código diretamente da Internet ".

Você pode passar por isso para referência

ykombinator
fonte
"código não seguro não pode ser executado em um ambiente não confiável." Você quis dizer "confiável"?
quer tocar hoje
18

sim, existem usos reais, quando o desempenho é crítico e as operações são de baixo nível

por exemplo, eu só precisei usar ponteiros em c # uma vez, para comparação de imagens. O uso do GetPixel em um par de imagens de 1024x1024x32 levou 2 minutos para fazer a comparação (correspondência exata). Fixar a memória da imagem e usar ponteiros levou menos de 1 segundo (na mesma máquina, é claro).

Steven A. Lowe
fonte
2
Já usei o LockBits para isso ... ( msdn.microsoft.com/en-us/library/… )
configurator
1
@configurator: este era o .net 2, o LockBits não existia
Steven A. Lowe
2
Claro que existia desde 1.0 ...
configurator
@ configurador: meu erro, fiquei confuso ao navegar na documentação do MSDN (quando mudei para .net 2 na lista suspensa, ele foi para uma página completamente diferente que não mencionava os lockbits). Sim, é assim que você fixa a memória da imagem.
Steven A. Lowe
6

Você deve se lembrar que os designers da Microsoft são pessoas inteligentes e tudo o que adicionam ao C # tem pelo menos 1 caso de uso. O projeto FParsec usa código não seguro para trazer toda a última gota de desempenho que o C # é capaz. Observe o uso de fixede 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
fonte
1
Eu diria que os desenvolvedores (na Microsoft ou em qualquer outra empresa) seriam idiotas se incluíssem algum recurso porque possui um caso de uso. Um recurso deve ter muito mais do que apenas 1 casos de uso; caso contrário, é um inchaço.
Lie Ryan
4
Raymond Chen costuma dizer que os recursos da Microsoft começam em -100 "pontos". Para que um recurso seja implementado, ele "precisa ter um efeito positivo líquido significativo no pacote geral para que ele seja inserido". Aqui está o post de ericgu sobre este c.2004: blogs.msdn.com/b/ericgu/archive/2004/01/12/57985.aspx
Jesse Buchanan
Tenho certeza de que algumas operações String internamente usam código não seguro. Portanto, o FParsec pode não ter sido a prioridade.
Arturo Torres Sánchez
4

Uma vez eu tive que usar ponteiros (no contexto inseguro) em um aplicativo Windows baseado em C # que atuaria como uma interface para um fone de ouvido. Esse aplicativo é uma interface do usuário que permitiria aos agentes (em um call center) controlar suas configurações de fone de ouvido. Este aplicativo funciona como uma alternativa ao painel de controle fornecido pelo fabricante do fone de ouvido. Assim, sua capacidade de controlar os fones de ouvido era limitada quando comparada às opções disponíveis. Eu tive que usar ponteiros porque tive que usar a API (uma DLL do Visual C ++) fornecida pelo fabricante do fone de ouvido usando P / Invoke.

k25
fonte