Udostępnij za pośrednictwem


System.String.Intern metoda

Uwaga / Notatka

Ten artykuł zawiera dodatkowe uwagi dotyczące dokumentacji referencyjnej dla tego interfejsu API.

Środowisko uruchomieniowe języka wspólnego obsługuje tabelę nazywaną pulą intern, która zawiera pojedyncze odwołanie dla każdej unikatowej wartości ciągu. Metoda Intern używa puli internowanych do wyszukiwania ciągu znaków równego wartości str. Jeśli taki ciąg nie istnieje, odwołanie do str zostanie dodane do puli, a to odwołanie zostanie zwrócone. (Natomiast metoda IsInterned(String) zwraca odwołanie o wartości null, jeśli żądany ciąg nie istnieje w puli internów.)

Pula intern może być używana przez środowisko uruchomieniowe do oszczędzania magazynu ciągów. Jednak automatyczne internowanie literałów ciągu nie jest gwarantowane — w zależności od tego, jak zestawienie zostało skompilowane i wykonane, niektóre literały mogą nie być dodane do puli.

W poniższym przykładzie ciąg s1 ma wartość "MyTest". Klasa System.Text.StringBuilder generuje nowy obiekt ciągu, który ma taką samą wartość jak s1. Odwołanie do tego ciągu jest przypisane do s2. Metoda Intern wyszukuje ciąg, który ma taką samą wartość jak s2. Jeśli s1 został już zainternowany (na przykład, ponieważ zestaw wymaga internowania literału ciągu), metoda zwraca to samo odwołanie co s1, które jest następnie przypisane do s3, oraz s1 i s3 porównują się jako równe. W przeciwnym razie zostanie utworzony nowy wpis zinternowany dla s2 i przypisany do s3, a s1 i s3 nie będą równe w porównaniu. W każdym z tych przypadków s1 i s2 są nierówne, ponieważ odnoszą się do różnych obiektów.

string s1 = "MyTest"; 
string s2 = new StringBuilder().Append("My").Append("Test").ToString(); 
string s3 = String.Intern(s2); 
Console.WriteLine((Object)s2==(Object)s1); // Different references.
Console.WriteLine((Object)s3==(Object)s1); // The same reference.
let s1 = "MyTest"
let s2 = StringBuilder().Append("My").Append("Test").ToString()
let s3 = String.Intern s2
printfn $"{s2 :> obj = s1 :> obj}" // Different references.
printfn $"{s3 :> obj = s1 :> obj}" // The same reference.
Dim s1 As String = "MyTest" 
Dim s2 As String = New StringBuilder().Append("My").Append("Test").ToString() 
Dim s3 As String = String.Intern(s2) 
Console.WriteLine(CObj(s2) Is CObj(s1))      ' Different references.
Console.WriteLine(CObj(s3) Is CObj(s1))      ' The same reference.

Zagadnienia dotyczące wydajności

Jeśli próbujesz zmniejszyć łączną ilość pamięci przydzielanej przez aplikację, pamiętaj, że internowanie ciągu, czyli przechowywanie ich w jednej kopii w pamięci, ma dwa niepożądane skutki uboczne. Po pierwsze, pamięć przydzielona dla obiektów internowanych String prawdopodobnie nie zostanie wydana, dopóki środowisko uruchomieniowe języka wspólnego (CLR) nie zakończy działania. Przyczyną jest to, że odwołanie CLR do zainternowanego obiektu może utrzymywać się nawet po zakończeniu działania twojej aplikacji lub jej domeny aplikacyjnej. Po drugie, aby internować ciąg, musisz najpierw utworzyć ciąg. Pamięć używana przez obiekt String musi być nadal przydzielana, mimo że pamięć zostanie ostatecznie zebrana jako śmieci.

Członek wyliczenia CompilationRelaxations.NoStringInterning oznacza zestawienie jako niewymagające internowania literału ciągu. Domyślnie kompilator języka C# emituje CompilationRelaxationsAttribute z flagą NoStringInterning dla każdego modułu w celu uzyskania lepszej wydajności, co oznacza, że literały ciągów nie są gwarantowane do dodania do puli intern. Można dostosować komponent NoStringInterning przy użyciu atrybutu CompilationRelaxationsAttribute.

W przypadku publikowania aplikacji przy użyciu natywnej funkcji AOT wyłączenie NoStringInterning nie jest obsługiwane. W przypadku natywnej funkcji AOT literały ciągu nie mają gwarancji dodania do puli intern, więc Intern może nie znaleźć dopasowania dla ciągu, który wydaje się być literałem w kodzie źródłowym.