显式实现接口时装箱的成本有多大

发布于 2024-07-09 01:31:12 字数 4135 浏览 4 评论 0原文

当前显式成员实现的指南建议:

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

一个很好的例子是当您想要实现 IXmlSerialized 接口。 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 方法的装箱成本如何。 ((IXmlSerialized)this).WriteXml(writer) 会显着影响性能吗?

The current guidlelines for explicit member implementation recommend:

  • Using explicit members to approximate private interface implementations. If you need to implement an interface for only infrastructure reasons and you never expect developers to directly call methods on that interface from this type then implement the members explicitly to 'hide' them from public view.
  • Expose an alternative way to access any explicitly implemented members that subclasses are allowed to override.

A good example of this is when you want to implement the IXmlSerializable interface. The ReadXml and WriteXml methods are expected to be called by the XmlSerializer and are not typically called directly by developers.

When providing an alternative way to access explicitly members you wish to allow to be overridden, it seems to make sense to call the explicitly implemented member so as to avoid code duplication. Consider the following:

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

My question is in regards to how expensive the boxing of the WriteXml method is in this implementation. Is ((IXmlSerializable)this).WriteXml(writer) going to significantly hinder performance?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

幼儿园老大 2024-07-16 01:31:12

您的示例中没有发生装箱...它只是一个强制转换,并且可以在编译时解析,因此它根本不会对性能产生任何影响。

编辑:使用 ILDASM 查看它,接口转换将为您提供虚拟方法调用与常规方法调用,但这可以忽略不计(仍然不涉及装箱)。

编辑2:如果您使用结构而不是类,那么您将得到一个通过界面的框,这会带来更多的性能损失。

There's no boxing taking place in your example... it's just a cast, and it's resolvable at compile time, so it should not have any impact on performance at all.

Edit: Looking at it with ILDASM, the interface cast will give you a virtual method call versus a regular method call, but this is negligible (there is still no boxing involved).

Edit 2: If you use a struct instead of a class, THEN you will get a box going through the interface, with much more of a performance penalty.

梦幻之岛 2024-07-16 01:31:12

不,将一堆数据写入 XmlWriter 的成本将使装箱成本相形见绌。

装箱包括:

  1. 从 GC 分配一块内存 使用
  2. 正确的类型信息初始化其标头
  3. 将值类型数据复制到堆内存中

因此,它与对象构造大致相同。 如果您要写入 XmlWriter 的单条数据还不是字符串,则无论如何您都必须付出此成本来构造要写入的字符串。

No, the cost of writing a bunch of data to an XmlWriter is going to dwarf the boxing cost.

Boxing consists of:

  1. Allocating a slice of memory from the GC
  2. Initializing its header with the correct type information
  3. Copying the valuetype data into the heap memory

As such, it's about the same as an object construction. If even a single piece of data that you're writing to the XmlWriter isn't already a string, you'll have to pay this cost anyway, to construct the string to write.

娇纵 2024-07-16 01:31:12

为什么不让它们都调用一个私有方法来执行显式实现的接口的功能呢?

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 )
{
    ...
}

Why not just have them both call a private method that performs the function of the explicitly implemented interface?

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 )
{
    ...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文