2016-06-21 8 views
1

Ich habe eine Methode, die ich in C# schreibe, die eine Zeichenfolge akzeptiert, die ein XML-Dokument enthält, und ein Array von Streams, die XSDs sind. Das String Dokument richtet sich gegen die XSDs validiert:C#: Sollen Streams in der aufgerufenen Methode geschlossen/entsorgt werden?

private static XmlValidationResult ValidateDocumentInternal(string document, params Stream[] xsdStreams) 
{ 
    XmlReaderSettings settings = new XmlReaderSettings 
    { 
     ValidationType = ValidationType.Schema 
    }; 

    foreach (var xsdStream in xsdStreams) 
    { 
     using (xsdStream) 
     { 
      XmlReader xmlReader = XmlReader.Create(xsdStream); 

      try 
      { 
       settings.Schemas.Add(null, xmlReader); 
      } 
      finally 
      { 
       xmlReader.Close(); 
      } 
     } 
    } 

    var validationErrors = new List<string>(); 

    settings.ValidationEventHandler += (object sender, System.Xml.Schema.ValidationEventArgs e) => 
    { 
     validationErrors.Add($"({e.Exception.LineNumber}): {e.Message}"); 
    }; 

    using (var stream = document.ToStream()) 
    { 
     var reader = XmlReader.Create(stream, settings); 

     while (reader.Read()) 
     { 
     } 
    } 

    return new XmlValidationResult 
    { 
     Success = validationErrors.Count == 0, 
     ValidationErrors = validationErrors 
    }; 
} 

Meine Frage ist, sollte diese Methode des XSD Stromes sein entsorgen oder soll, dass die Verantwortung des Anrufers sein? Stellen Sie sich den folgenden Code, der in dem Dokument gelangt und XSD und erwartet ValidateDocumentInternal die XSD Strom zu entsorgen:

var document = GetDocument(); 
Stream xsd = GetXSD(); 
var validationResult = ValidateDocumentInternal(document, xsd); 

oder sie sein sollte, wie (nicht in ValidateDocumentInternal des Stroms Entsorgung):

var document = GetDocument(); 
using (Stream xsd = GetXSD()) { 
    var validationResult = = ValidateDocumentInternal(document, xsd); 
} 

oder alternativ sollte ich einfach in eine bool sagen, ob zu entsorgen oder nicht?

+3

Es könnte eine Frage des Geschmacks aber sein persönlich würde ich deine zweite Option bevorzugen ('using'). – Heinzi

+1

Ich habe Streams immer in dem Bereich geschlossen, in dem sie erstellt wurden, sodass sie in Wirklichkeit die Verantwortlichkeit des Aufrufers ist und nicht in der Blackbox einer Methodenimplementierung geschieht. Einige .net-APIs bieten jedoch eine Markierung an, um Besitz von der Entsorgung zu übernehmen ... Sie könnten dies auch als optionalen Parameter anbieten, der standardmäßig auf "false" gesetzt ist. – spender

+1

Ich übernehme normalerweise die Regel "Der Code, der den Stream erstellt, ist dafür verantwortlich, ihn zu schließen". In einigen Fällen ist dies unangemessen, zum Beispiel wenn dadurch der Stream für eine sehr lange Zeit geöffnet bleibt. Was auch immer Sie tun, es ist wichtig zu dokumentieren, was der Aufrufer mit dem Stream macht - dies gilt für jeden Parameter, bei dem der Aufrufer den Status des bereitgestellten Objekts ändert, aber die Leute übersehen oft, dass jemand, der einen Stream liest, seinen Status ändert. –

Antwort

4

Ich denke, es ist die Verantwortung des Anrufers - es ist ein Parameter von der Funktion von jemand anderem gegeben. Die Funktion kann nicht wissen, ob es in einem anderen Kontext verwendet wird und und ändern, dass es tun wird ist eigentlich ein "Nebeneffekt" ... den ich persönlich stark versuche zu vermeiden

+0

Das scheint eigentlich ganz vernünftig. Sie können die Position im Stream immer wieder auf 0 setzen und erneut verwenden. –

+1

Könnte wahr sein, aber das bedeutet, dass Code, der nach (oder schlechter, vielleicht parallel zu) dieser Funktion passiert, wissen muss, dass die Funktion einen Nebeneffekt hat. Ich denke, deine zweite Option beim Benutzen ist die bessere Übung. –