C# 使用C语言中的(IDisposable obj=new…)在流中编写代码块(例如XML)
我已经开始使用实现IDisposable的类,使用using语句在流中写入块。这有助于保持正确的嵌套,避免丢失或错误放置起始/结束零件 基本上,构造函数写块的开始(例如打开XML标记),Dispose()写块的结束(例如关闭XML标记)。下面的例子是UsableXmlElement(它适用于大型XML,所以内存中的LINQ-to-XML或XmlDocument没有选项) 但是,这些IDisposable没有实现Microsoft推荐的复杂模式,包括析构函数/终结器、单独的Dispose(bool)方法和GC.SuppressFinalize()。Dispose只写end元素,就这样 这有什么不好的地方吗?或者这是保持元素正确嵌套的好方法吗C# 使用C语言中的(IDisposable obj=new…)在流中编写代码块(例如XML),c#,xml,stream,idisposable,using-statement,C#,Xml,Stream,Idisposable,Using Statement,我已经开始使用实现IDisposable的类,使用using语句在流中写入块。这有助于保持正确的嵌套,避免丢失或错误放置起始/结束零件 基本上,构造函数写块的开始(例如打开XML标记),Dispose()写块的结束(例如关闭XML标记)。下面的例子是UsableXmlElement(它适用于大型XML,所以内存中的LINQ-to-XML或XmlDocument没有选项) 但是,这些IDisposable没有实现Microsoft推荐的复杂模式,包括析构函数/终结器、单独的Dispose(bool
class UsableXmlElement : IDisposable
{
private XmlWriter _xwriter;
public UsableXmlElement(string name, XmlWriter xmlWriter)
{
_xwriter = xmlWriter;
_xwriter.WriteStartElement(name);
}
public void WriteAttribute<T>(string name, T value)
{
_xwriter.WriteStartAttribute(name);
_xwriter.WriteValue(value);
_xwriter.WriteEndAttribute();
}
public void WriteValue<T>(T value)
{
_xwriter.WriteValue(value);
}
public void Dispose()
{
_xwriter.WriteEndElement();
}
}
导致:
<RootElement DocVersion="123">
<InnerElement>
<!-- anything -->
</InnerElement>
</RootElement>
有什么不好的地方吗
不可以。无论如何都应该避免使用析构函数(终结器),即使是有资源的类通常也可以(更好)不使用
或者这是维护元素正确嵌套的好方法吗
class UsableXmlElement : IDisposable
{
private XmlWriter _xwriter;
public UsableXmlElement(string name, XmlWriter xmlWriter)
{
_xwriter = xmlWriter;
_xwriter.WriteStartElement(name);
}
public void WriteAttribute<T>(string name, T value)
{
_xwriter.WriteStartAttribute(name);
_xwriter.WriteValue(value);
_xwriter.WriteEndAttribute();
}
public void WriteValue<T>(T value)
{
_xwriter.WriteValue(value);
}
public void Dispose()
{
_xwriter.WriteEndElement();
}
}
对。你可以作为参考
这些IDisposable不实现Microsoft推荐的复杂模式
“完整”模式是正确的,但过时了。它仅描述“裸”非托管资源的情况。不幸的是,没有提供仅用于处理托管资源的官方参考资料 我看到的主要缺点(除了使用using语句的非标准用法可能违反了“最小意外原则”)是,如果XmlWriter
引发异常,它将尝试重复写入所有嵌套的结束标记
至少在理论上,在编写内部结束标记时可能会引发异常,然后在using语句生成的“finally”块中成功写入外部结束标记。这将导致无效输出。创建microsoft使用的复杂模式是为了确保释放非托管资源,即使您不调用
Dispose()
在类中不使用任何非托管资源。您只需利用C#的使用
关键字,使代码更具可读性和可维护性。我认为这是一个很好的方法,我过去也用过
我认为使用finalizer构造是没有意义的,因为您需要确保在正确的位置写入end标记。您永远不知道何时调用终结器,因此如果忘记处理元素,则无法确定何时会写入结束标记。您的Xml文档仍然会乱七八糟,不管是否完全没有写入结束标记,还是在错误的位置
在最坏的情况下,当终结器调用Dispose()时,XmlWriter可能已经被释放,您会得到一个异常。所以最好不要使用终结器。为什么会出现问题?在UsableXmlElement中不需要任何非托管资源,因此不需要任何终结器,我认为……哦,而且不需要将WriteValue和WriteAttribute作为泛型。它什么都不做,因为xwriter.WriteValue总是用对象参数调用。从未听说过它被称为“最小惊喜原则”。我以后会用这个表达:)