2

明示的なメンバー実装の現在のガイドラインでは、次のことを推奨しています。

  • 明示的なメンバーを使用して、プライベートインターフェイスの実装を概算します。インフラストラクチャの理由のみでインターフェイスを実装する必要があり、開発者がこのタイプからそのインターフェイスのメソッドを直接呼び出すことを期待しない場合は、メンバーを明示的に実装して、パブリックビューからそれらを「非表示」にします
  • サブクラスがオーバーライドを許可されている明示的に実装されたメンバーにアクセスするための代替方法を公開します。

この良い例は、IXmlSerializableインターフェースを実装する場合です。ReadXmlメソッドとWriteXmlメソッドは、XmlSerializerによって呼び出されることが期待されており、通常、開発者によって直接呼び出されることはありません。

オーバーライドを許可したいメンバーに明示的にアクセスする別の方法を提供する場合、コードの重複を避けるために、明示的に実装されたメンバーを呼び出すことは理にかなっているようです。次のことを考慮してください。

using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace Demo
{
    /// <summary>
    /// Demonstrates explicit implementation of the IXmlSerializable interface.
    /// </summary>
    [Serializable(), XmlRoot(ElementName = "foo")]
    public class Foo : IXmlSerializable
    {
        //============================================================
        //  IXmlSerializable Implementation
        //============================================================
        #region GetSchema()
        /// <summary>
        /// Returns an <see cref="XmlSchema"/> that describes the XML representation of the object.
        /// </summary>
        /// <returns>
        /// An <see cref="XmlSchema"/> that describes the XML representation of the object that is 
        /// produced by the <see cref="IXmlSerializable.WriteXml(XmlWriter)"/> method and consumed by the <see cref="IXmlSerializable.ReadXml(XmlReader)"/> method.
        /// </returns>
        /// <remarks>This method is reserved and should not be used.</remarks>
        XmlSchema IXmlSerializable.GetSchema()
        {
            return null;
        }
        #endregion

        #region ReadXml(XmlReader reader)
        /// <summary>
        /// Generates an object from its XML representation.
        /// </summary>
        /// <param name="reader">The <see cref="XmlReader"/> stream from which the object is deserialized.</param>
        /// <exception cref="ArgumentNullException">The <paramref name="reader"/> is a <b>null</b> reference (Nothing in Visual Basic).</exception>
        void IXmlSerializable.ReadXml(XmlReader reader)
        {
            // Class state values read from supplied XmlReader
        }
        #endregion

        #region WriteXml(XmlWriter writer)
        /// <summary>
        /// Converts an object into its XML representation.
        /// </summary>
        /// <param name="writer">The <see cref="XmlWriter"/> stream to which the object is serialized.</param>
        /// <exception cref="ArgumentNullException">The <paramref name="writer"/> is a <b>null</b> reference (Nothing in Visual Basic).</exception>
        void IXmlSerializable.WriteXml(XmlWriter writer)
        {
            // Current class state values written using supplied XmlWriter
        }
        #endregion

        //============================================================
        //  Public Methods
        //============================================================
        #region WriteTo(XmlWriter writer)
        /// <summary>
        /// Saves the current <see cref="Foo"/> to the specified <see cref="XmlWriter"/>.
        /// </summary>
        /// <param name="writer">The <see cref="XmlWriter"/> stream to which the <see cref="Foo"/> is serialized.</param>
        /// <exception cref="ArgumentNullException">The <paramref name="writer"/> is a <b>null</b> reference (Nothing in Visual Basic).</exception>
        public void WriteTo(XmlWriter writer)
        {
            writer.WriteStartElement("foo");

            ((IXmlSerializable)this).WriteXml(writer);

            writer.WriteEndElement();
        }
        #endregion
    }
}

私の質問は、この実装でのWriteXmlメソッドのボクシングのコストに関するものです。(( IXmlSerializable )this).WriteXml(writer)は、パフォーマンスを大幅に低下させますか?

4

3 に答える 3

5

この例ではボクシングは行われていません...これは単なるキャストであり、コンパイル時に解決できるため、パフォーマンスにまったく影響を与えないはずです。

編集: ILDASMで見ると、インターフェイスキャストは、通常のメソッド呼び出しと比較して仮想メソッド呼び出しを提供しますが、これはごくわずかです(ボクシングはまだ含まれていません)。

編集2:クラスの代わりに構造体を使用すると、インターフェイスを通過するボックスが表示されますが、パフォーマンスが大幅に低下します。

于 2008-12-02T02:03:22.567 に答える
3

いいえ、XmlWriterに大量のデータを書き込むコストは、ボクシングのコストを小さくします。

ボクシングは以下で構成されています:

  1. GCからのメモリのスライスの割り当て
  2. 正しいタイプ情報でヘッダーを初期化する
  3. 値型データをヒープメモリにコピーする

そのため、オブジェクトの構築とほぼ同じです。XmlWriterに書き込んでいるデータの1つでもまだ文字列でない場合は、書き込む文字列を作成するために、とにかくこのコストを支払う必要があります。

于 2008-12-02T02:02:26.560 に答える
1

明示的に実装されたインターフェースの機能を実行するプライベートメソッドを両方に呼び出させないのはなぜですか?

public void IXmlSerializable.WriteXml( XmlWriter writer )
{
    InternalWriteXml( writer );
}

public void WriteTo(XmlWriter writer)
{
    writer.WriteStartElement("foo");

    InternalWriteXml(writer);

    writer.WriteEndElement();
}

private void InternalWriteXml( XmlWriter writer )
{
    ...
}
于 2008-12-02T02:04:09.663 に答える