System.Stringはクラスであるため参照型になりますが、通常の参照型とは見かけ上の挙動が異なります。

s2s1を代入した時点で両者は同じインスタンスを参照することになり、その後s1"bar"を代入すれば同じ参照となっているs2"bar"となる、という挙動を予想することもできますが、実際にはs2"foo"のままとなります。

このような結果となるのは、s1"bar"を代入している箇所で新しい文字列型のインスタンス"bar"が生成され、それがs1に代入されているためです。 上記のコードが次のようなコードで動作しているととらえるとその挙動が理解しやすいかもしれません(擬似コードのため実際には動作しません)。

参照型としての文字列型の挙動を理解するための疑似コード
Imports System

Class Sample
  Shared Sub Main()
    Dim s1 As String = New String("foo")
    Dim s2 As String = s1

    Console.WriteLine("{0} {1}", s1, s2)

    s1 = New String("bar")

    Console.WriteLine("{0} {1}", s1, s2)
  End Sub
End Class