String.Intern(String) Metoda

Definicja

Pobiera odwołanie systemu do określonego Stringelementu .

public:
 static System::String ^ Intern(System::String ^ str);
public static string Intern(string str);
static member Intern : string -> string
Public Shared Function Intern (str As String) As String

Parametry

str
String

Ciąg do wyszukania w puli internowej.

Zwraca

Odwołanie systemu do strmetody , jeśli jest internowane; w przeciwnym razie nowe odwołanie do ciągu o wartości str.

Wyjątki

Parametr str ma wartość null.

Przykłady

Poniższy przykład tworzy dwa ciągi o równych wartościach i pokazuje, że ich przeplatanie daje to samo odwołanie.

// Sample for String.Intern(String)
using System;
using System.Text;

class Sample
{
    public static void Main()
    {
        string s1 = new StringBuilder().Append("My").Append("Test").ToString();
        string s2 = new StringBuilder().Append("My").Append("Test").ToString();
        Console.WriteLine($"s1 == {s1}");
        Console.WriteLine($"s2 == {s2}");
        Console.WriteLine($"Are s1 and s2 equal in value? {s1 == s2}");
        Console.WriteLine($"Are s1 and s2 the same reference? {Object.ReferenceEquals(s1, s2)}");

        string i1 = String.Intern(s1);
        string i2 = String.Intern(s2);
        Console.WriteLine($"After interning:");
        Console.WriteLine($"  Are i1 and i2 equal in value? {i1 == i2}");
        Console.WriteLine($"  Are i1 and i2 the same reference? {Object.ReferenceEquals(i1, i2)}");
    }
}
/*
This example produces the following results:
s1 == MyTest
s2 == MyTest
Are s1 and s2 equal in value? True
Are s1 and s2 the same reference? False
After interning:
  Are i1 and i2 equal in value? True
  Are i1 and i2 the same reference? True
*/
// Sample for String.Intern(String)
open System
open System.Text

let s1 = StringBuilder().Append("My").Append("Test").ToString()
let s2 = StringBuilder().Append("My").Append("Test").ToString()
printfn $"s1 = {s1}"
printfn $"s2 = {s2}"
printfn $"Are s1 and s2 equal in value? {s1 = s2}"
printfn $"Are s1 and s2 the same reference? {Object.ReferenceEquals(s1, s2)}"

let i1 = String.Intern s1
let i2 = String.Intern s2
printfn "After interning:"
printfn $"  Are i1 and i2 equal in value? {i1 = i2}"
printfn $"  Are i1 and i2 the same reference? {Object.ReferenceEquals(i1, i2)}"
(*
This example produces the following results:
s1 = MyTest
s2 = MyTest
Are s1 and s2 equal in value? True
Are s1 and s2 the same reference? False
After interning:
  Are i1 and i2 equal in value? True
  Are i1 and i2 the same reference? True
*)
Imports System.Text

Class Sample

    Public Shared Sub Run()
        Dim s1 As String = New StringBuilder().Append("My").Append("Test").ToString()
        Dim s2 As String = New StringBuilder().Append("My").Append("Test").ToString()
        Console.WriteLine($"s1 = {s1}")
        Console.WriteLine($"s2 = {s2}")
        Console.WriteLine($"Are s1 and s2 equal in value? {s1 = s2}")
        Console.WriteLine($"Are s1 and s2 the same reference? {s1 Is s2}")

        Dim i1 As String = String.Intern(s1)
        Dim i2 As String = String.Intern(s2)
        Console.WriteLine("After interning:")
        Console.WriteLine($"  Are i1 and i2 equal in value? {i1 = i2}")
        Console.WriteLine($"  Are i1 and i2 the same reference? {i1 Is i2}")
    End Sub
End Class
'
's1 = MyTest
's2 = MyTest
'Are s1 and s2 equal in value? True
'Are s1 and s2 the same reference? False
'After interning:
'  Are i1 and i2 equal in value? True
'  Are i1 and i2 the same reference? True
'

Uwagi

! [UWAGA] > Chociaż String.Intern gwarantuje, że dwa ciągi o równych wartościach zwracają to samo odwołanie internowane, nie gwarantuje, że zwrócone odwołanie jest takie samo jak literał ciągu.

        The common language runtime maintains a table, called the *intern pool*, that holds a single reference for each unique string value. The <xref:System.String.Intern*> method uses the intern pool to search for a string equal to the value of `str`. If no such string exists, a reference to `str` is added to the pool, and that reference is returned. (In contrast, the <xref:System.String.IsInterned(System.String)> method returns a null reference if the requested string doesn't exist in the intern pool.)

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.

Dotyczy

Zobacz też