Ponteiros na unidade C #

8

Ei, eu acabei de aprender sobre ponteiros recentemente e estou me perguntando como posso usá-los em c # (acabei de aprender sobre eles em c ++) em unidade. Eu tenho algumas perguntas, no entanto.

  1. Os ponteiros usam programação de baixo nível para encontrar posições de valores diferentes no computador. Isso significa que você pode acessar apenas o valor de uma variável a partir de qualquer script?
  2. Em caso afirmativo, como faço para chamar um local de uma variável com apenas seu código de local?
  3. Existem diferenças discerníveis entre ponteiros em C # e C ++ que eu deveria saber?
  4. Como posso usar ponteiros com os tipos de variáveis ​​no Unity (Vector3s, Transforms, GameObjects, etc ...)?

Provavelmente, há muitas outras perguntas que eu deveria fazer e gostaria de fazer uma pergunta, se você tiver informações ou fontes adicionais.

Ryan Henry
fonte

Respostas:

6

Em geral, para C # e especificamente para Unity, eu desaconselharia ... mas se você realmente quisesse ou tivesse um bom motivo, poderia.

Em C #, você precisaria se familiarizar com o que é chamado de código inseguro . Assustado ainda?

No Unity, seria necessário ativar o modo de compilação não seguro, para que você não possa usar o web player se planejou isso. Você pode ler mais aqui ou aqui .

Então, basicamente, o C # foi projetado com um Garbage Collector como muitas linguagens de script. A idéia geral é tentar abstrair a noção de gerenciamento de memória para simplificar o desenvolvimento. Você ainda pode acabar com vazamentos de recursos se não anular seus objetos. Sinceramente, não sou um grande apoiador dos GCs e preferiria os métodos RAII , mas este é o mundo em que vivemos.

A maioria dos desenvolvedores de C ++ também concorda, no entanto, que você não deve usar ponteiros diretamente e prefere usar um tipo projetado para RAII, também conhecido como ponteiros inteligentes . Se você estiver em terra C, provavelmente os ponteiros são uma segunda natureza para você, mas mesmo assim isso ajuda a abstraí-los até certo ponto.

Se você usá-los em C #, esteja ciente de que existe um potencial muito real, você pode adicionar vulnerabilidades de segurança ou realmente desagradáveis ​​e difíceis de rastrear bugs. Você também deve ter em mente que deve tomar cuidado para não fazer referência a objetos que podem ser movidos pelo GC. Observe o uso da instrução fixa aqui .

Você também pode usar ponteiros no Unity escrevendo um plug-in nativo . Isso novamente descartará as compilações do webplayer, mas o novo recurso HTML5 funciona com base no emscripten; portanto, se você planejou usá-lo, provavelmente faria isso se tomar cuidado. Os plugins nativos permitem que você estenda o Unity em uma base por plataforma. Eu escrevi um plugin nativo para se comunicar com alguns microcontroladores através de uma conexão serial, por exemplo.

Então, para resumir, você deve definitivamente se perguntar por que quero usar ponteiros em C # no Unity. Se você só quer fazer isso por diversão ... Nocauteie-se.

Edit: Me desculpe se eu ofendi alguém, pois sei que meus pensamentos sobre a GC não são da opinião popular no momento.

Se você realmente ler minha resposta, notará que eu não chamo o C # de uma linguagem de script. Comparo-o a "muitas linguagens de script", no entanto, no contexto do Unity, é muito usado como uma linguagem de script. É uma espécie de DSL para Unity, se você preferir. Muitas vezes, você o verá referido como Script do Unity nesse contexto (isso se refere principalmente à alternativa Javascript do Unity ao C #). Se você colocar o LLVM em seu pipeline, poderá compilá-lo diretamente no código nativo da plataforma ... então como você o chamaria? Então, na verdade, eu não queria dividir os cabelos aqui.

Muitas ótimas referências à engenharia de software estão cheias de opiniões:

Effective C ++ , mais eficaz C ++ , C ++ FAQ , eficaz C # , design ++ Modern C , Design Patterns ... E inúmeros outros. Não acho que isso torne os argumentos menos credíveis se forem seguidos de explicações ponderadas.

Eu não estava realmente dizendo: "Nunca use ponteiros!" . Na verdade, eu ainda os uso nus de vez em quando. Eu disse "em geral", como em "prefiro usar código seguro para código não seguro em C #". Há situações em que isso pode ser benéfico, e esse é um dos recursos realmente poderosos do C # para escolher suas ferramentas. O C # ainda permite que você tenha transparência no processo de GC em algum grau, idiomas como o Dart não têm e podem levar a vazamentos de recursos com muita facilidade. Claro, se você é o único desenvolvedor de um projeto pequeno, provavelmente não é um problema. Se você estiver em uma equipe de digamos 10+ com centenas de milhares de linhas de código, pode ser complicado.

Eu simplesmente queria que o leitor tivesse cuidado ao usar ponteiros nus. É como dizer muito cuidado ao trabalhar com eletricidade da rede elétrica. Não estou dizendo que não seja eletricista, apenas se você fizer o movimento errado e não o tratar com respeito, estará morto.

Eu gosto do exemplo dado por Lasse no qual o desempenho pode ter ditado a necessidade.

Matthew Sanders
fonte
11
C # não é uma linguagem de script, embora possa ser usada para isso. O Java também possui um GC e também não é uma linguagem de script. Responder com sua própria opinião o que é melhor em geral, não é a resposta objetiva que estamos procurando neste site. Para uma finalidade específica, algo como código e ponteiros inseguros pode ser realmente eficiente.
Lasse
11
Não entendo por que essa resposta foi rebaixada - é muito informativa e mostra muita pesquisa / conhecimento e links para outras leituras. Especialmente para @Lasse, o que é linguagem de script? É claro que seria mais preciso dizer "linguagem que é usada para script em unidade", mas não vejo muitas razões para recusar porque Matthew omitiu 7 palavras óbvias e usou um termo (mais) simplificado.
Wondra
@wondra Eu não votei porque a resposta não está tornando óbvio que existem lugares onde os ponteiros podem muito bem ser usados ​​em C #. Tudo depende do objetivo e da plataforma de destino. De fato, a resposta está tentando assustar todo mundo para não usar ponteiros.
Lasse
11
@wondra Esta resposta dificilmente está respondendo à pergunta. Tudo o que faz é dizer para não usar ponteiros. Esta seção de comentários não é o lugar apropriado para discutir isso. Você pode participar do bate-papo se achar que tem mais argumentos.
Lasse
11
O @Lasse não pode convencê-lo e não é minha luta, mas vendo a sua resposta - você escreveu exatamente o mesmo que esta resposta (que foi postada mais cedo); além disso, você incluiu apenas um subconjunto (= menos informações) no tópico como esta resposta.
Wondra
6

O C # usa referências para passar objetos que não são do tipo valor . Isso significa que tudo é geralmente passado por referência. Se você deseja passar um tipo de valor por referência, pode usar a palavra-chave ref . A diferença de um tipo de referência e um tipo de valor é que, dependendo do tamanho do tipo de valor, ele geralmente requer mais memória copiada quando é passada para uma função. Uma referência é de apenas 32 bits ou 64 bits ou 4 bytes ou 8 bytes. Você pode obter mais desempenho do seu código em loops muito apertados se usar referências em vez de apenas copiar todos os dados que as variáveis ​​digitadas por valor contêm, supondo que sejam maiores que 4 ou 8 bytes.

Por exemplo, no Unity, qualquer objeto MonoBehaviour (classe) é um tipo de referência e qualquer objeto Vector3 (struct) é do tipo Valor.

Também existem blocos de código inseguros que permitem digitar códigos que permitem criar e modificar dados inseguros. Para usar código não seguro, você precisará definir o compilador para permitir código não seguro. Ponteiros podem ser usados ​​dessa maneira. Ao usar código não seguro, algumas verificações não são usadas com código seguro, o que dificulta a gravação de código não seguro sem erros. Existem muito poucos lugares que podem se beneficiar de código não seguro em C #. No Unity, o código não seguro não é suportado em todas as plataformas. Normalmente, usar referências em vez de ponteiros não seguros é suficiente ao trabalhar com o Unity.

Aqui está um exemplo ( fonte ) do uso de ponteiros de código não seguros em C # com Unity:

public static class Rope
{
    // C# function declaration to match C++
    [DllImport(SlingshotImport.c_libName)]
    static unsafe extern void UpdateRopeParticlesUnsafe(
        Vector3* oldNew,
        Vector3* curr,
        int numParticles);

    // C# wrapper function for Unity C# script
    static void UpdateRopeParticles(
        Vector3[] oldNew,
        Vector3[] curr,
        int numParticles)
    {
        unsafe
        {
            fixed (Vector3* oldNewPtr = oldNew)
            fixed (Vector3* currPtr = curr)
            {
                UpdateRopeParticlesUnsafe(oldNewPtr, currPtr, numParticles);
            }
        }
    }
}
Lasse
fonte
Acho interessante que você critique minha resposta e use os mesmos argumentos, menos outras informações relevantes, e inclua apenas uma breve discussão sobre o valor versus os tipos de referência. Você poderia, pelo menos menção Boxe , otimizações JIT que pode, por vezes, remover o tipo de valor copiar sobrecarga, como evitar inseguro pela triagem , ou talvez que o código inseguro nem sempre mais rápido, então segura é
Matthew Sanders
Sinto muito se você se sentir atacado ou ofendido. Não era minha intenção. Critiquei sua resposta por me parecer muito baseada em opiniões, e não em fatos. Forneci respostas para as perguntas feitas, juntamente com algum código de exemplo. Pela sua resposta, não consegui entender as coisas que expliquei na minha resposta, que senti serem mais relevantes para a pergunta. Não vejo como o GC tem algo a ver com "como uso ponteiros?" ou não vi você mencionar como as referências funcionam em C #, pois a pergunta parecia assumir que variáveis ​​funcionavam da mesma maneira em C # e C ++.
Lasse
11
Não se preocupe. Obrigado pelo seu pedido de desculpas. Mencionei o GC porque você precisa estar ciente de que a passagem de ponteiros para tipos gerenciados pode causar problemas se o GC mover o objeto repentinamente. Eu assumi que o leitor estava ciente do sistema do tipo C # e como os tipos de referência versus valor são usados.
Matthew Sanders
Vocês realmente tornam difícil aceitar uma resposta. Vocês dois me forneceram muitas informações necessárias, então vou votar em vocês dois e vou aceitar o que veio primeiro. Não quero dizer nada com isso. Eu apenas tenho dificuldade em escolher e quanto a me assustar do "código inseguro", não se preocupe. Eu nunca fui o único a desistir de qualquer desafio. Embora agora eu saiba que trabalhar com ponteiros é impraticável, pois se refere ao desenvolvimento de várias plataformas. Quero agradecer a todos pelo seu tempo e opiniões. e me desculpe, eu comecei a Segunda Guerra Mundial não meen para fazer isso.
Ryan Henry