Como caro é o boxe ao implementar explicitamente uma interface
-
22-07-2019 - |
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?
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:
- A alocação de uma fatia de memória a partir do GC
- Inicializar seu cabeçalho com o tipo de informação correta ??li>
- 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 )
{
...
}