Condividi tramite


Oggetti XName e XNamespace atomizzati (LINQ to XML)

XName gli oggetti e XNamespace vengono atomizzati, ovvero se contengono lo stesso nome qualificato, fanno riferimento allo stesso oggetto. Ciò offre vantaggi in termini di prestazioni per le query: quando si confrontano due nomi atomizzati per verificarne l'uguaglianza, il linguaggio intermedio sottostante deve solo determinare se i due riferimenti puntano allo stesso oggetto. Il codice sottostante non deve eseguire confronti tra stringhe, che richiederebbero più tempo.

Semantica di atomizzazione

L'atomizzazione significa che se due XName oggetti hanno lo stesso nome locale e si trovano nello stesso spazio dei nomi, condividono la stessa istanza. Allo stesso modo, se due XNamespace oggetti hanno lo stesso URI dello spazio dei nomi, condividono la stessa istanza.

Per consentire a una classe di abilitare gli oggetti atomizzati, il costruttore per la classe deve essere privato, non pubblico. Ciò è dovuto al fatto che se il costruttore era pubblico, è possibile creare un oggetto non atomizzato. Le classi XName e XNamespace implementano un operatore di conversione implicita per convertire una stringa in un XName o un XNamespace. Questo è il modo in cui si ottiene un'istanza di questi oggetti. Non è possibile ottenere un'istanza usando un costruttore, perché il costruttore non è accessibile.

XName e XNamespace implementano anche gli operatori di uguaglianza e disuguaglianza, che determinano se i due oggetti confrontati sono riferimenti alla stessa istanza.

Esempio: Creare oggetti e mostrare che nomi identici condividono un'istanza

Il codice seguente crea alcuni XElement oggetti e dimostra che gli stessi nomi condividono la stessa istanza.

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

In questo esempio viene generato l'output seguente:

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.

Come accennato in precedenza, il vantaggio degli oggetti atomici è che quando si usa uno dei metodi dell'asse che accettano come XName parametro, il metodo dell'asse deve solo determinare che due nomi fanno riferimento alla stessa istanza per selezionare gli elementi desiderati.

Nell'esempio seguente, viene passato un XName alla chiamata al metodo Descendants, che di conseguenza ha prestazioni migliori grazie al modello di atomizzazione.

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

In questo esempio viene generato l'output seguente:

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