c# - studio - Anidado usando declaraciones y análisis de código de Microsoft
generar documentacion visual studio 2017 (2)
Recientemente encendí reglas de análisis de código adicionales. Para mi sorpresa, vi una violación en un lugar que siempre estaba considerando como la mejor práctica. Si tengo dos elementos desechables anidados, estoy poniendo dos declaraciones de uso como esta:
using (StringReader strReader = new StringReader(xmlString))
using (XmlReader xmlReader = XmlReader.Create(strReader))
{
result.ReadXml(xmlReader);
}
Esto también corresponde a las preguntas y respuestas anidadas de mayor calificación utilizando declaraciones en C #
La violación me sale estados siguientes:
Warning 18 CA2202 : Microsoft.Usage : Object ''strReader'' can be disposed more
than once in method ''????''. To avoid generating a System.ObjectDisposedException
you should not call Dispose more than one time on an object.: Lines: ??
Lo que hice fue un intento de error intuitivo, pensando que cerca del flujo externo probablemente también eliminaría el interno, arreglé rápidamente mi código de esta manera:
using (XmlReader xmlReader = XmlReader.Create(new StringReader(xmlString)))
{
result.ReadXml(xmlReader);
}
Hura! La advertencia se ha ido. Pero, tada! El nuevo se produjo:
Warning 18 CA2000 : Microsoft.Reliability : In method ''????????'', object
''new StringReader(xmlString)'' is not disposed along all exception paths. Call
System.IDisposable.Dispose on object ''new StringReader(xmlString)'' before all
references to it are out of scope.
Entonces encontré una solución muy fea:
{
StringReader strReader = null;
try
{
strReader = new StringReader(xmlString);
using (XmlReader xmlReader = XmlReader.Create(strReader))
{
strReader = null;
result.ReadXml(xmlReader);
}
}
finally
{
if (strReader != null) strReader.Dispose();
}
}
Como último paso (como todo buen programador) busqué en la página de ayuda de CA2202 y, para mi sorpresa, ¿exactamente mi última solución UGLY fue propuesta para solucionar el problema?
¡Haber intentado {} finalmente usar el código de clutters mucho! Para mí es el anidado usando mucho más legible.
Pregunta: ¿Hay una mejor manera de hacer las cosas? Estoy buscando una solución que sea intuitivamente comprensible. Todos los que vean este último fragmento tendrán curiosidad sobre lo que está sucediendo.
Gracias de antemano por sus respuestas.
El problema no es por los usos anidados. Están bien y generalmente recomendados. El problema aquí es que XmlReader
eliminará el TextReader
si pasas un XmlReaderSettings
con CloseInput == true
, pero la regla CA2202 no es lo suficientemente inteligente como para que tu código no baje esa rama. Mantenga sus usos anidados y suprima la violación de CA2202 como un falso positivo.
Si desea ser explícito en su código para mejorar su legibilidad y / o facilidad de mantenimiento, use un XmlReaderSettings
con CloseInput
establecido en false
, pero ese es el valor predeterminado, por lo que no es estrictamente necesario y, para ser claro, no satisfacer la regla
Por cierto, hay escenarios de problemas CA2202 similares para una variedad de tipos de flujo y lector. Desafortunadamente, no todos son iguales a este, por lo que el mejor manejo de casos puede variar según el tipo de problema.
Hace poco tuve un problema similar, pero como estaba usando un serializador tuve que adaptarlo, ya que no pude establecer el stringWriter en nulo de inmediato. Esta solución evita todos los avisos de CA:
StringWriter stringWriter = null;
XmlWriter xmlWriter = null;
string serializedValue = null;
try
{
XmlSerializer xmlserializer = new XmlSerializer(typeof(T));
stringWriter = new StringWriter();
xmlWriter = XmlWriter.Create(stringWriter);
xmlserializer.Serialize(xmlWriter, value);
xmlWriter.Flush();
serializedValue = stringWriter.ToString();
}
finally
{
if (xmlWriter != null) //Both objects need disposed
{
xmlWriter.Dispose(); //stringWriter will dispose automatically too
}
else if (stringWriter != null) //XmlWriter failed to create
{
stringWriter.Dispose(); //just dispose stringWriter
}
}