2016-06-21 2 views
1

私は、XML文書を含む文字列とXSDであるストリームの配列を受け入れるC#で書いているメソッドを持っています。文字列の文書は、のXSDに対して検証されていますC#:ストリームを呼び出されたメソッドで閉じたり破棄したりする必要がありますか?

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

私の質問は、この方法は、XSDの流れを処分しなければならない場合、またはそれは、呼び出し側の責任ですべきですか?

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

またはそれが(ValidateDocumentInternalにストリームを廃棄しない)ようにする必要があります:

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

または文書とXSDに渡すと期待しValidateDocumentInternalをXSDストリームを配置するには、次のコードを想像してみて代わりに、私はちょうどbool処分するかどうかを言って渡す必要がありますか?

+3

味の問題かもしれませんが個人的には、私はあなたの第2のオプション( '使用する')を好むでしょう。 – Heinzi

+1

私は、作成されたスコープ内のストリームを常にクローズしています。そのため、メソッド実装のブラックボックスでストリームを作成するのではなく、呼び出し元の責任にしています。しかし、一部の.net APIは、廃棄の所有権を取得するためのフラグを提供しています...省略可能な省略可能なパラメータとしてfalseを指定することもできます。 – spender

+1

私は通常、「ストリームを作成するコードはそれを閉じる責任があります」というルールを採用しています。これが不適切な場合があります。たとえば、ストリームが非常に長い間開いている場合などです。あなたが何をするにしても、発信者がストリームで行うことを文書化することが重要です。これは、呼び出し元が提供されたオブジェクトの状態を変更するすべてのパラメータに当てはまりますが、ストリームを読む誰かがその状態を変更していることをよく見落とします。 –

答えて

4

私はそれが発信者の責任であると思います。それは、他の人が関数から与えたパラメータです。この関数は別のコンテキストで使用されているかどうかを知ることができず、それが行う変更は実際には「副作用」です...私が個人的に強くしているのは避けてください

+0

それは実際にはかなり賢明なようです。ストリーム上の位置を常に0に戻して再利用することができます。 –

+1

これは真実かもしれませんが、これは、この関数の後に起こるコード(あるいは悪い、おそらく並行している)が関数に副作用があることを知っている必要があることを意味します。私はあなたの2番目のオプションを使用してより良い習慣だと思う。 –

関連する問題