System.String dziwne zachowanie?

Hejka! 🙂

Wracam po 4 miesięcznej przerwie! Zmieniłem pracę i z czasem było dość krucho…

Dzisiaj, na rozgrzewkę, zaprezentuję małą ciekawostkę, jaką możecie napotkać podczas korzystania z klasy System.String.


string hello = "Hello World";
string hello2 = "Hello World";

Console.WriteLine("Equals:" + Equals(hello, hello2));
Console.WriteLine("ReferenceEquals: " + ReferenceEquals(hello, hello2));

Jak zapewne wiemy, String jest klasą referencyjną – wyjątkową, bo jego metoda Equals porównuje wartości ciągów znakowych zamiast referencji. W tym przypadku jesteśmy pewni, że ciągi są identyczne.

Otrzymany wynik – true.

Natomiast co z drugim przypadkiem, z użyciem ReferenceEquals? 

Przypomnę – jest to metoda znajdująca się w klasie bazowej System.Object, porównująca referencje przekazanych obiektów.

Otrzymujemy również true.

Dlaczego?

Osobne dwa stringi zostały zainicjowane, a zatem powinniśmy uzyskać dwie osobne referencje. Z wyniku metody ReferenceEquals wnioskujemy, że wskazują na ten sam obszar pamięci.

Wniosek?

Kompilator C# jest na tyle sprytny i optymalizuje dany kod, kompilując oba stringi do jednej instancji. Technika ta nazywa się string pooling.

Oczywiście dane stringi muszą być znane w trakcie kompilacji…

Zalety?

  • oszczędność pamięci
  • szybsze porównanie stringów – ta sama instancja
string hello = "Hello World";
string hello2 = string.Copy("Hello World");
Console.WriteLine("Equals: " + Equals(hello, hello2));
Console.WriteLine("ReferenceEquals: " + ReferenceEquals(hello, hello2));

Używanie metody statycznej string.Copy gwarantuje nam utworzenie kopii stringa. Dzięki temu otrzymamy wynik potwierdzający, że dwa stringi nie współdzielą tej samej instancji.