Udostępnij za pośrednictwem


Atomized XName i XNamespace objects (LINQ to XML)

XName obiekty i XNamespaceatomizowane; oznacza to, że jeśli zawierają tę samą kwalifikowaną nazwę, odwołują się do tego samego obiektu. Daje to korzyści z wydajności zapytań: podczas porównywania dwóch atomizowanych nazw równości podstawowy język pośredni musi określić, czy dwa odwołania wskazują ten sam obiekt. Kod źródłowy nie musi wykonywać porównań ciągów, co trwa dłużej.

Semantyka atomizacji

Atomizacja oznacza, że jeśli dwa XName obiekty mają taką samą nazwę lokalną i są w tej samej przestrzeni nazw, współużytkują to samo wystąpienie. W ten sam sposób, jeśli dwa XNamespace obiekty mają ten sam identyfikator URI przestrzeni nazw, współużytkują to samo wystąpienie.

Aby klasa umożliwiała atomizowane obiekty, konstruktor klasy musi być prywatny, a nie publiczny. Jest to spowodowane tym, że jeśli konstruktor był publiczny, można utworzyć nie atomizowany obiekt. Klasy XName i XNamespace implementują niejawny operator konwersji, aby przekonwertować ciąg na element XName lub XNamespace. W ten sposób uzyskujesz wystąpienie tych obiektów. Nie można uzyskać wystąpienia przy użyciu konstruktora, ponieważ konstruktor jest niedostępny.

XName a XNamespace także zaimplementować operatory równości i nierówności, które określają, czy dwa porównywane obiekty są odwołaniami do tego samego wystąpienia.

Przykład: tworzenie obiektów i wyświetlanie identycznych nazw współużytkujących wystąpienie

Poniższy kod tworzy niektóre XElement obiekty i pokazuje, że identyczne nazwy współużytkują to samo wystąpienie.

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

Ten przykład generuje następujące wyniki:

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.

Jak wspomniano wcześniej, zaletą atomizowanych obiektów jest użycie jednej z metod osi, które przyjmują XName jako parametr, metoda osi musi tylko określić, że dwie nazwy odwołują się do tego samego wystąpienia, aby wybrać żądane elementy.

Poniższy przykład przekazuje metodę XNameDescendants do wywołania metody, która ma lepszą wydajność ze względu na wzorzec atomizacji.

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

Ten przykład generuje następujące wyniki:

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