2

当前显式成员实现的指导方针建议:

  • 使用显式成员来近似私有接口实现。如果您仅出于基础设施的原因需要实现一个接口,并且您从不期望开发人员直接从该类型调用该接口上的方法,那么显式地实现成员以“隐藏”它们对公共视图
  • 公开一种替代方法来访问允许子类覆盖的任何显式实现的成员。

一个很好的例子是当您想要实现IXmlSerializable接口时。ReadXmlWriteXml方法应由 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 的单个数据还不是字符串,那么无论如何您都必须支付此成本来构造要写入的字符串。

于 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 回答