Em C# existem Value Types e Reference Types. Value Types são tipos que são sempre passados por valor. Atribuir uma variável a outra na prática copia o seu valor, se for um tipo simples (int, byte) ou copia seus membros se for uma struct. Passar um value type como parâmetro para um método implica na cópia do seu valor para esse parâmetro. Reference Types são sempre passados por referência. Objetos de classes são sempre reference types. Na prática objetos são ponteiros que apontam para a área na memória onde os dados do objeto estão de verdde. Atribuir uma variável contendo um objeto para outra variável NÃO duplica o objeto. Na verdade você tem duas variáveis apontando para o mesmo objeto, mas continua com um objeto só. Passar uma variável do tipo reference type como argumento para um método resulta em passar uma referência para o próprio objeto, e ele pode ser modificado. Outra diferença fundamental é com relação a área de memória do programa que os tipos são guardados. Value Types são alocados na Stack, enquanto que Reference Types são guardados na Heap. Uma exceção à regra são as Strings. Strings são Reference Types, mesmo assim se comportam como Value Types. Isso é feito para facilitar o seu uso pelo Dev. Alguns objetos são Reference Types mas podem ter alguns métodos especiais, como override do .Equals e do operador == para se comportarem como Value Types. Strings são esse tipo de objeto.
- Objetos são instâncias de classes e são tipos de referência (reference types)
- Variáveis do tipo Struct são Value Types
- Records são tipos especiais de classes que já tem o override do .Equals e do operador == feitos pelo compilador, sem a necessidade de ser feito pelo desenvolvedor. Isso garante que eles se comportem parcialmente como Value Types.
- Tipos criados com as palavras chave
record
estruct
ao mesmo tempo são tipos Value Types, alocados na Stack e ainda possuem o override do operador == já feito pelo compilador. Assim estruturas mais complexas podem se comportar como um simples int ou byte e o operador == é válido para comparar duas variáveis desse tipo.
- atribuir, passar como argumento para um método ou retornar de um método um valor do tipo Value Type implica na cópia do valor
- atribuir, passar como argumento ou retornar um Reference Type significa passar uma referência para o objeto na memória
- Se um método altera um Value Type o valor alterado só é acessível dentro do método.
- Se um método altera um Reference Type o objeto original é alterado, e as alterações podem ser vistas fora do método.
- Strings são exceções a regra: elas são Reference Types por definição, mas se comportam como Value Types
- Value Types são alocados na Stack.
- Reference Types são alocados na Heap.