인터페이스를 명시 적으로 구현할 때 얼마나 많은 비용이 박히는가
-
22-07-2019 - |
문제
명시적인 회원 구현을위한 현재 가이드 라인은 다음을 권장합니다.
- 명시 적 멤버를 사용하여 개인 인터페이스 구현을 근사화합니다. 인프라 이유만으로 인터페이스를 구현 해야하는 경우 절대 개발자 가이 유형에서 해당 인터페이스에서 메소드를 직접 호출 할 것을 기대하고 회원을 명시 적으로 구현하여 공개보기에서 '숨기기'.
- 서브 클래스가 재정의 할 수있는 명시 적으로 구현 된 멤버에 액세스하는 대체 방법을 노출시킵니다.
이것의 좋은 예는 당신이 구현하고 싶을 때입니다. ixmlserializable 상호 작용. 그만큼 readxml 그리고 쓰기 xml 방법은 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
}
}
내 질문은 쓰기 xml 이 구현에 메소드가 있습니다. ~이다 ((ixmlserializable) this) .writexml (Writer) 성능을 크게 방해할까요?
해결책
당신의 예에서는 권투가 일어나지 않습니다 ... 그것은 단지 캐스트 일 뿐이며 컴파일 시간에 해결할 수 있으므로 성능에 전혀 영향을 미치지 않아야합니다.
편집하다: ildasm으로 그것을 살펴보면 인터페이스 캐스트는 가상 메소드 호출 대 정기적 인 메소드 호출을 제공하지만 이는 무시할 수 있습니다 (여전히 권투가 포함되어 있지 않음).
편집 2 : 클래스 대신 구조물을 사용하는 경우 훨씬 더 많은 성능 페널티가있는 인터페이스를 통과하는 상자를 얻게됩니다.
다른 팁
아니요, XMLWriter에게 많은 데이터를 작성하는 데 드는 비용은 복싱 비용을 따돌릴 것입니다.
권투는 다음으로 구성됩니다.
- GC에서 메모리 한 조각을 할당합니다
- 올바른 유형 정보로 헤더를 초기화합니다
- ValueType 데이터를 힙 메모리에 복사합니다
따라서 객체 구성과 거의 같습니다. XMLWriter에 쓰는 단일 데이터조차도 아직 문자열이 아닌 경우, 문자열을 작성하려면 어쨌든이 비용을 지불해야합니다.
명시 적으로 구현 된 인터페이스의 기능을 수행하는 개인 메소드를 호출하게하는 이유는 무엇입니까?
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 )
{
...
}