Principais Diferenças

(OBS: Este tutorial encontra-se bastante incompleto. Se puder, ficaremos gratos em receber um Pull Request seu)

Se você veio de C++, o caminho é bem mais simples quanto se você viesse de C.

Assim como foi feito com C, segue uma pequena tabela com algumas das diferenças entre C# e C++:

RecursoCC#
PonteirosSimNão¹
Classes/ObjetosSim. Não herdam por padrãoSim, e definem ReferenceTypes². Herdam de Object.
StructsSimSim, mas definem ValueTypes²
MacrosSimSim³
NamespacesSimSim
Function-pointerSimPossui Delegates e Events
HerançaSimSim
InterfaceSim (classes puramente virtuais)Sim (com a keyword interface)
TemplatesSimPossui Generics⁴

¹: Sim, mas apenas em um bloco unsafe.

²: ValueTypes e ReferenceTypes são conceitos já conhecidos em C++, mas vale ver em que contextos C# trata um ou outro.

³: C# tem macros, mas não da mesma forma que C: elas apenas definem símbolos que podem ser utilizados em #ifndef, por exemplo, mas não servem para definir constantes. Também não há a necessidade de include-guards.

Uma das maiores diferenças que você provavelmente irá notar é que, em C#, tudo precisa estar em uma classe, não existe nada “solto” (incluindo o main, que fica marcado como um método estático e os argumentos da linha de comando ficam em um array de strings).

No geral não haverão muitas diferenças na forma de modelar o código. Algumas nomenclaturas, apesar de iguais, funcionam de forma diferente. São elas:

using

  • Um using não pode ser utilizado dentro de qualquer escopo como em C++;
  • using, em C#, possui três funções:
    • Incluir namespaces, como o using do C++ mesmo, porém apenas no escopo geral;
    • Criar aliases para Namespaces;
    • Criar aliases para classes (serve tanto para resolver ambiguidade quanto para importar apenas o que precisar de uma determinada namespace).

struct

  • Não há a diferença de modificador de acesso padrão entre Classes (que em C++ é private) e Structs (que em C++ é public): o padrão de ambos é internal;
  • Structs, por serem ValueTypes, são sempre recebidas como cópia: não há como enviar uma referência de uma struct senão indicando explicitamente com a keyword ref (é necessário que a função também defina o parâmetro como ref, e nesse caso apenas refs podem ser passadas para aquele parâmetro em específico).

Outras diferenças menores

  • Para acessar um elemento de uma namespace se utiliza namespace.something em vez de namespace::something;
  • ++i e i++ não possuem diferença de performance;
  • TODO

std::optional

Em C#, apesar de que ValueTypes não são referências, é possível criar uma versão "Nullable" deles utilizanod um ? após o tipo. Ela acaba funcionando como std::optional, e pode ser vista aqui: