Pergunta

Os guidlelines atuais para implementação de membro explícito recomendo:

  • Usando membros explícitos para aproximar implementações interface privada. Se você precisa implementar uma interface para apenas razões de infra-estrutura e você não esperar que os desenvolvedores para chamar diretamente métodos nessa interface deste tipo, em seguida, implementar os membros explicitamente a 'esconder'-los da vista do público .
  • Expor uma forma alternativa de acesso quaisquer membros explicitamente implementados que subclasses estão autorizados a substituição.

Um bom exemplo disso é quando você deseja implementar o IXmlSerializable interface. O ReadXml e WriteXml métodos são esperados para ser chamado pelo XmlSerializer e não são normalmente chamados diretamente pelos desenvolvedores.

Ao fornecer uma forma alternativa de acesso explicitamente membros que você deseja permitir para ser substituído, parece fazer sentido para chamar o membro explicitamente implementado de forma a duplicação de código evitar. Considere o seguinte:

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
    }
}

A minha pergunta é em relação à forma como caro o boxe do WriteXml método é nesta implementação. É ((IXmlSerializable) este) .WriteXml (escritor) vai significativamente prejudicar o desempenho?

Foi útil?

Solução

Não há nenhuma boxe ocorrendo no seu exemplo ... é apenas um elenco, e é resolvido em tempo de compilação, por isso não deve ter nenhum impacto sobre o desempenho em tudo.

Editar:. Olhando para ele com ILDASM, o elenco interface irá dar-lhe uma chamada de método virtual versus uma chamada de método regular, mas isso é insignificante (ainda não existe um boxe envolvidos)

Editar. 2: Se você usar um struct em vez de uma classe, então você vai ter uma caixa de atravessar a interface, com muito mais de uma penalidade de desempenho

Outras dicas

Não, o custo de escrever um monte de dados para um XmlWriter vai anão o custo de boxe.

Boxe consiste em:

  1. A alocação de uma fatia de memória a partir do GC
  2. Inicializar seu cabeçalho com o tipo de informação correta
  3. Copiar os dados valuetype na memória heap

Como tal, é aproximadamente o mesmo que uma construção objeto. Se até mesmo uma única peça de dados que você está escrevendo para o XmlWriter não é já uma string, você vai ter que pagar este custo de qualquer maneira, para construir a string de escrever.

Porque não basta ter os dois chamar um método particular que realiza a função da interface implementada explicitamente?

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 )
{
    ...
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top