1

I'm Writing to 2 files at a time from a row in a csv, basically I have a list of rows that some have errors so I want to create a log file with detailed errors per row and a new csv with all these rows that had errors, so I'm opening 2 streamwriters at a time, so instead of doing a using block within a using block im doing

using (var writer = new StreamWriter[] { new StreamWriter(infoFolderPath + "/Import Errors.txt"), new StreamWriter(infoFolderPath + "/Failed Import Rows.csv") })
{
    foreach (var err in rowsWithErrors)
    {
        writer[0].WriteLine(Write row error here...);
        writer[1].WriteLine(Write row in csv here...);
    }
}

But the problem with this is I get an error 'StreamWriter[]': type used in a using statement must be implicitly convertible to 'System.IDisposable'. I understand that I need to be able to dispose of the Stream after its done and the using block cant find the Dispose method because its an array of type stream and not of type stream.

So my question is, is there a way to make this work or a smarter way to write to a few files?

(please don't answer to make 2 using statements because I'm writing to more then 2 files I just simplified for the question to be easy to understand...)

9
  • Is the number of files unbounded? Commented Aug 30, 2022 at 12:27
  • @RobertHarvey it is bounded Commented Aug 30, 2022 at 12:28
  • What is the maximum number of files? Commented Aug 30, 2022 at 12:29
  • 1
    using statements can be stacked, without the need of additional braces. See stackoverflow.com/a/1329765/102937 Commented Aug 30, 2022 at 12:35
  • 1
    Also consider that you may also just be trying to do too much in a single method, if it's a complex operation with a lot of state. If those writers were fields of an object, you could dispose of them in the Dispose of that object, and creating them would also be separate from your core logic. Commented Aug 30, 2022 at 12:39

1 Answer 1

3

Change it to a try/finally block instead which is what using equates to.

var writer = new StreamWriter[] { new StreamWriter(infoFolderPath + "/Import Errors.txt"), new StreamWriter(infoFolderPath + "/Failed Import Rows.csv") }
try
{
    foreach (var err in rowsWithErrors)
    {
        writer[0].WriteLine(Write row error here...);
        writer[1].WriteLine(Write row in csv here...);
    }
}
finally
{
    foreach(var w in writer)
    {
      w.Dispose();
    }
}

Based on the comments it is always 4 streams. I would personally just stack the using statements (or var if using a supported c# version). Notice that there is no additional indentation for each additional using statement. This also allows you to give meaningful names to your variables (unlike my code example below).

using (var writer1 = new StreamWriter(infoFolderPath + "/Import Errors.txt"))
using (var writer2 = new StreamWriter(infoFolderPath + "/Failed Import Rows.csv"))
using (var writer3 = new StreamWriter(infoFolderPath + "/other.txt"))
using (var writer4 = new StreamWriter(infoFolderPath + "/other2.txt"))
{
    foreach (var err in rowsWithErrors)
    {
        writer1.WriteLine(Write row error here...);
        writer2.WriteLine(Write row in csv here...);
        writer3.WriteLine(Write row error here...);
        writer4.WriteLine(Write row in csv here...);
    }
}

If you are using c# 8 or higher you can reduce the nesting even more with var using.

using var writer1 = new StreamWriter(infoFolderPath + "/Import Errors.txt");
using var writer2 = new StreamWriter(infoFolderPath + "/Failed Import Rows.csv");
using var writer3 = new StreamWriter(infoFolderPath + "/other.txt");
using var writer4 = new StreamWriter(infoFolderPath + "/other2.txt");

foreach (var err in rowsWithErrors)
{
    writer1.WriteLine(Write row error here...);
    writer2.WriteLine(Write row in csv here...);
    writer3.WriteLine(Write row error here...);
    writer4.WriteLine(Write row in csv here...);
}
Sign up to request clarification or add additional context in comments.

7 Comments

What if one of those throw in their dispose call
@DanielA.White - According to MS best practices Dispose should always swallow any Exceptions thrown but yes, that could happen although I am not sure specifically about the implementation of StreamWriter if it does this or not. You would have to wrap the Dispose in a try/catch in the loop.
ah, didn't know you can stack them... both good answers, thx a million
I second the stacked using recommendation, also consider using var declaration, i.e. using var writer1 = ...
the project I'm working on is still C# version 7.3 and this feature is from C# v8.0 and greater...
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.