cuando se habla de pasar un objeto por valor se habla de que el procedimeinto crea un objeto nuevo con base al parametro.
En .NET los objetos que son instancias de clase ( la gran mayoria, los que quedan en el heap) se pasan siempre por referencia, mientras que objetos creados a partir de estructs o de tipos de dato 'nativos' por defecto se pasan por valor y es opcional pasarlos por referencia.
Cuando se pasa un parametro por referencia lo que se hace 'tras vanbalinas' es pasar un apuntador al objeto, asi pues cuando se pasan objetos instancia de clase como parametro, lo que se esta pasando es realmente un apuntador a esa seccion de memoria en el heap y cuando se pasan estructuras o tipos nativos se pasa un apuntador a la seccion de memoria creada en el stack. Cuando se pasa un parameto que es de tipo struct o tipo nativo se crea una copia del espacio de memoria reservado en el stack y esta es la que se manipula desde el procedimiento.