Todos los objectos se pasan por referencia en C#, los datos primitivos se pasan por valor, pero al momento de que tu haces la declaración, lo que estás haciendo es únicamente reservar un espacio en la memoria para dichos objetos, y cuando ya los inicializas, esos objetos, son redireccionados o tienen la dirección del objeto o valor al cual tu los inicializaste. Por ejemplo, tu inicializas el objecto obj1, obj2, entonces, obj1 tendrá la dirección en memoria 101, obj2 tiene la dirección 102 (todo esto es suposición para aclarar el concepto) hasta ahí no tienes ningún valor ni nada por el estilo, pero cuando haces la inicialización como:
"obj1 = 5;"
"obj2 = 6;"
La dirección de obj1 apuntará a la dirección en memoria 201 (por decir así) que es donde se encuentra en memoria el dato 5, y la dirección de obj2 (102) apuntará a la dirección en memoria 202 que es donde se encuentra el dato 6, entonces, los dos objetos están haciendo referencia un dato primitivo, y al momento de ponerle obj2 = obj1, el obj2 apuntará hacia la misma dirección donde apunta obj1, o sea, hacia el dato 5.
Esto es el concepto básico de las instancias u objetos bro, debido a que las variables (mejor dicho) obj1 y obj2 están haciendo referencia a un dato primitivo, éstas se comportan como dichos datos primitivos, en este caso, como enteros, te pongo un ejemplo básico, para que te des cuenta que en realidad se comportan como datos primitivos.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ObjectTest
{
class Program
{
static void Main(string[] args)
{
Object obj1, obj2;
obj1 = 4;
obj2 = obj1;
Console.WriteLine("El valor del obj1 es : {0}",obj1.ToString());
Console.WriteLine("El valor del obj2 es: {0}",obj2.ToString());
Console.WriteLine("nAgregándo a obj2 el valor de 6nn");
obj2 = 6;
Console.WriteLine("El valor del obj1 es : {0}", obj1.ToString());
Console.WriteLine("El valor del obj2 es: {0}", obj2.ToString());
Console.WriteLine("nEl tipo de valor de obj1 es: {0}", obj1.GetType().ToString());
Console.WriteLine("El tipo de valor de obj2 es: {0}", obj2.GetType().ToString());
Console.ReadLine();
}
}
}
Te darás cuenta que en los dos te dirá System.Int32, esto es porque las variables tipo obj, pueden almacenar o compotarse como cualquier tipo de variable