Estruturas e campos simples facilitarão a interoperabilidade com algumas APIs não gerenciadas. Frequentemente, você descobrirá que a API de baixo nível deseja acessar os valores por referência, o que é bom para o desempenho (como evitamos uma cópia desnecessária). O uso de propriedades é um obstáculo para isso e, muitas vezes, as bibliotecas do wrapper fazem cópias para facilitar o uso e, às vezes, para segurança.
Por esse motivo, você geralmente obtém melhor desempenho com tipos de vetores e matrizes que não têm propriedades, mas campos nus.
As melhores práticas não estão criando no vácuo. Apesar de algum culto à carga, em geral as melhores práticas existem por um bom motivo.
Nesse caso, temos alguns:
Uma propriedade permite alterar a implementação sem alterar o código do cliente (em nível binário, é possível alterar um campo para uma propriedade sem alterar o código do cliente no nível de origem, no entanto, ele será compilado para algo diferente após a alteração) . Isso significa que, usando uma propriedade desde o início, o código que faz referência à sua não precisará ser recompilado apenas para alterar o que a propriedade faz internamente.
Se nem todos os valores possíveis dos campos do seu tipo forem estados válidos, você não deseja expô-los ao código do cliente que o modifica. Portanto, se algumas combinações de valores forem inválidas, você deseja manter os campos privados (ou internos).
Eu tenho dito o código do cliente. Isso significa código que chama no seu. Se você não está criando uma biblioteca (ou mesmo fazendo uma biblioteca, mas usando interno, em vez de público), geralmente pode se safar e ter uma boa disciplina. Nessa situação, a melhor prática de usar propriedades está presente para impedir que você atire no próprio pé. Além disso, é muito mais fácil raciocinar sobre o código se você puder ver todos os lugares onde um campo pode mudar em um único arquivo, em vez de precisar se preocupar com o que está sendo modificado ou não em outro lugar. De fato, as propriedades também são boas para colocar pontos de interrupção ao descobrir o que deu errado.
Sim, há valor em ver o que está sendo feito na indústria. No entanto, você tem motivação para ir contra as melhores práticas? ou você está apenas indo contra as melhores práticas - dificultando o raciocínio do código - apenas porque alguém fez isso? Ah, a propósito, "outros fazem isso" é como você inicia um culto à carga.
Então ... O seu jogo está lento? É melhor dedicar tempo para descobrir o gargalo e corrigi-lo, em vez de especular o que poderia ser. Você pode ter certeza de que o compilador fará muitas otimizações; por isso, é provável que você esteja procurando o problema errado.
Por outro lado, se você está decidindo o que fazer para começar, deve se preocupar com quais algoritmos e estruturas de dados primeiro, em vez de se preocupar com detalhes menores, como campos x propriedades.
Finalmente, você ganha alguma coisa contrariando as melhores práticas?
Para os detalhes do seu caso (Unity e Mono para Android), o Unity usa valores por referência? Caso contrário, ele copiará os valores de qualquer maneira, sem ganho de desempenho.
Se isso acontecer, se você estiver passando esses dados para uma API que leva ref. Faz sentido tornar o campo público ou você pode tornar o tipo capaz de chamar a API diretamente?
Sim, é claro, poderia haver otimizações que você poderia fazer usando estruturas com campos nus. Por exemplo, você os acessa com ponteiros Span<T>
ou similar. Eles também são compactos na memória, facilitando a serialização para envio pela rede ou armazenamento permanente (e sim, são cópias).
Agora, você escolheu os algoritmos e estruturas corretos, se eles se tornarem um gargalo, então você decide qual é a melhor maneira de corrigi-lo ... que poderia ser estruturas com campos nus ou não. Você poderá se preocupar com isso se e quando acontecer. Enquanto isso, você pode se preocupar com assuntos mais importantes, como tornar um jogo bom ou divertido que vale a pena jogar.