I was perplexed after executing this piece of code, where strings seems to behave as if they are value types. I am wondering whether the assignment operator is operating on
They don't. You changed the pointer of a2, not the object it pointed to.
When you are using classes and getting your expected behavior, you must be setting a property of the object, not its reference.
Any other class will behave the same:
Foo a = new Foo(1);
Foo b = a; //a, b point to the same object
b.Value = 4; // change property
Assert.Equals(a.Value, 4); //true - changed for a
b = new Foo(600); // new reference for b
Assert.Equals(a.Value, 4); //true
Assert.Equals(b.Value, 600); //true