Значение object.ReferenceEquals равно false, поскольку оно проверяет, указывают ли обе ссылки на один и тот же объект.ReferenceEquals не проверяет равенство данных, но если оба объекта занимают один и тот же адрес памяти.
Как уже упоминалось в TheGeneral, строковые литералы интернируются и хранятся в таблице, называемой внутренним пулом.Это необходимо для эффективного хранения строковых объектов.
Когда строковый литерал назначен нескольким переменным, они указывают на один и тот же адрес в пуле интернов.Следовательно, вы получаете истину для object.ReferenceEquals.Но когда вы сравниваете это с подстрокой, в памяти создается новый объект.Это приводит к ложному результату при сравнении ссылок, поскольку это два разных объекта, занимающих разные области памяти.
Все динамически созданные строки или чтение из внешнего источника автоматически не интернируются.
ЕслиЕсли вы попробуете следующее, вы получите true для object.ReferenceEquals:
Console.WriteLine(object.ReferenceEquals(s1, string.Intern(s4)));
Вы можете проверить с помощью типов данных Primitive, что ReferenceEquals возвращает false, даже если одна переменная назначена другой.
int a = 10;
int b = a;
Console.WriteLine(ReferenceEquals(a, b)); //false
Это потому, что каждый тип примитива хранится отдельно.