Short version:
No it shouldn't be pointing to the same address. It was pointing to the same address but you replaced the address in ABC with another (the result of the replace).
Long version
Think of it this way - the assignment operator (=) as well as passing arguments to a method and returning values from a method always does a copy. The difference between reference types and value types is what is copied. When the value is a value type the whole data in memory is copied to another place in memory. The variable itself contains the data. When working with reference types the variable (aslo method argument and method return value) holds the address of the object in memory. This is why when you assign one variable to another they point to the same object. Both variables store the same address. However the = operator still does a copy from one variable to the other. It copies the address. Therefore when you assign the return value from the replace method you copy the address of the new string in the variable ABC. You do not copy anything in the other variable. They used to point to the same object but now they don't because the address copied in ABC is now different. Variables of reference types are not linked by some magic they are linked by the fact that they hold addresses of the same object but the addresses themselves are just numbers. If you use the = operator on the variable you replace the object. If you change the object the value will change in both variables but if you replace the object the variables will hold different objects.
Note that this holds true for method arguments too.
List<string> list = new List<String> { "asdf" };
SomeMethod(list);
//list contains "asdf", "fdsa"
SoemOtherMethod(list),
//list is NOT null
static void SomeMethod(List<string> list)
{
list.Add("fdsa"); //changes the original list
}
static void SomeOtherMethod(List<string> list)
{
list = null; //cannot replace the original list only replaces the address in the argument variable
}