Freigeben über


Atomisierte XName- und XNamespace-Objekte (LINQ to XML)

XName und XNamespace Objekte werden atomisiert, d. h., wenn sie denselben qualifizierten Namen enthalten, verweisen sie auf dasselbe Objekt. Dies führt zu Leistungsvorteilen für Abfragen: Wenn Sie zwei atomisierte Namen für die Gleichheit vergleichen, muss die zugrunde liegende Zwischensprache nur bestimmen, ob die beiden Verweise auf dasselbe Objekt verweisen. Der zugrunde liegende Code muss keine Zeichenfolgenvergleiche durchführen, was länger dauern würde.

Atomisierungsemantik

Die Atomisierung bedeutet, dass zwei XName Objekte denselben lokalen Namen haben und sich im selben Namespace befinden, sie dieselbe Instanz verwenden. Wenn zwei XNamespace Objekte denselben Namespace-URI aufweisen, verwenden sie die gleiche Instanz.

Damit eine Klasse atomisierte Objekte aktivieren kann, muss der Konstruktor für die Klasse privat und nicht öffentlich sein. Dies liegt daran, dass Sie, wenn der Konstruktor öffentlich war, ein nicht atomisiertes Objekt erstellen könnten. Die XName- und XNamespace-Klassen implementieren einen impliziten Konvertierungsoperator, um eine Zeichenfolge in ein XName oder XNamespace zu konvertieren. Auf diese Weise können Sie eine Instanz dieser Objekte abrufen. Sie können eine Instanz nicht mithilfe eines Konstruktors abrufen, da auf den Konstruktor nicht zugegriffen werden kann.

XName und XNamespace implementieren ebenfalls die Gleichheits- und Ungleichheitsoperatoren, die bestimmen, ob die beiden verglichenen Objekte Verweise auf dieselbe Instanz sind.

Beispiel: Erstellen von Objekten und zeigen, dass identische Namen eine Instanz teilen

Der folgende Code erstellt einige XElement Objekte und veranschaulicht, dass identische Namen dieselbe Instanz verwenden.

var r1 = new XElement("Root", "data1");
XElement r2 = XElement.Parse("<Root>data2</Root>");

if ((object)r1.Name == (object)r2.Name)
    Console.WriteLine("r1 and r2 have names that refer to the same instance.");
else
    Console.WriteLine("Different");

XName n = "Root";

if ((object)n == (object)r1.Name)
    Console.WriteLine("The name of r1 and the name in 'n' refer to the same instance.");
else
    Console.WriteLine("Different");
Dim r1 As New XElement("Root", "data1")
Dim r2 As XElement = XElement.Parse("<Root>data2</Root>")

If DirectCast(r1.Name, Object) = DirectCast(r2.Name, Object) Then
    Console.WriteLine("r1 and r2 have names that refer to the same instance.")
Else
    Console.WriteLine("Different")
End If

Dim n As XName = "Root"

If DirectCast(n, Object) = DirectCast(r1.Name, Object) Then
    Console.WriteLine("The name of r1 and the name in 'n' refer to the same instance.")
Else
    Console.WriteLine("Different")
End If

Dieses Beispiel erzeugt die folgende Ausgabe:

r1 and r2 have names that refer to the same instance.
The name of r1 and the name in 'n' refer to the same instance.

Wie bereits erwähnt, ist der Vorteil atomisierter Objekte, dass bei Verwendung einer der Achsenmethoden, die als XName Parameter verwendet werden, die Achsenmethode nur bestimmen muss, dass zwei Namen auf dieselbe Instanz verweisen, um die gewünschten Elemente auszuwählen.

Im folgenden Beispiel wird ein XName an den Descendants Methodenaufruf übergeben, wodurch die Leistung aufgrund des Atomisierungsmusters verbessert wird.

var root = new XElement("Root",
    new XElement("C1", 1),
    new XElement("Z1",
        new XElement("C1", 2),
        new XElement("C1", 1)
    )
);

var query = from e in root.Descendants("C1")
            where (int)e == 1
            select e;

foreach (var z in query)
    Console.WriteLine(z);
Dim root As New XElement("Root", New XElement("C1", 1), New XElement("Z1", New XElement("C1", 2), New XElement("C1", 1)))

Dim query = From e In root.Descendants("C1") Where CInt(e) = 1

For Each z In query
    Console.WriteLine(z)
Next

Dieses Beispiel erzeugt die folgende Ausgabe:

<C1>1</C1>
<C1>1</C1>