次の方法で共有


アトム化された XName オブジェクトと XNamespace オブジェクト (LINQ to XML)

XName および XNamespace オブジェクトは アトミック化されます。つまり、同じ修飾名が含まれている場合は、同じオブジェクトを参照します。 これにより、クエリのパフォーマンス上の利点が得られます。2 つのアトミック化された名前を等しいかどうかを比較する場合、基になる中間言語は、2 つの参照が同じオブジェクトを指しているかどうかを判断するだけで済みます。 基になるコードは文字列比較を行う必要がないため、時間がかかります。

アトミック化セマンティクス

アトミック化とは、2 つの XName オブジェクトが同じローカル名を持ち、それらが同じ名前空間にある場合、同じインスタンスを共有することを意味します。 同様に、2 つの XNamespace オブジェクトが同じ名前空間 URI を持つ場合、同じインスタンスを共有します。

クラスでアトミック化されたオブジェクトを有効にするには、クラスのコンストラクターはパブリックではなくプライベートである必要があります。 これは、コンストラクターがパブリックの場合、非アトミック化されたオブジェクトを作成できるためです。 XNameクラスとXNamespace クラスは、文字列をXNameまたはXNamespaceに変換する暗黙的な変換演算子を実装します。 これは、これらのオブジェクトのインスタンスを取得する方法です。 コンストラクターにアクセスできないため、コンストラクターを使用してインスタンスを取得することはできません。

XName また、 XNamespace は等値演算子と不等値演算子も実装します。比較対象の 2 つのオブジェクトが同じインスタンスへの参照であるかどうかを判断します。

例: オブジェクトを作成し、同じ名前でインスタンスを共有することを示す

次のコードは、いくつかの XElement オブジェクトを作成し、同じ名前が同じインスタンスを共有することを示しています。

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

この例では、次の出力が生成されます。

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.

前述のように、アトミック化されたオブジェクトの利点は、 XName をパラメーターとして受け取る軸メソッドの 1 つを使用する場合、軸メソッドは、2 つの名前が同じインスタンスを参照して目的の要素を選択することを決定するだけで済むという点です。

次の例では、XName メソッド呼び出しにDescendantsを渡します。これにより、アトミック化パターンが原因でパフォーマンスが向上します。

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

この例では、次の出力が生成されます。

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