0

So I have a folder with only 2 text files, I am reading them and storing the value. This is what the code looks:

public static void UnionFiles()
{
    var dinfo =
        new DirectoryInfo(
            @"\http");
    var files = dinfo.GetFiles("*.txt");
    int i = 1;
    System.Collections.Generic.IEnumerable<String> _eValA, _eValB;

    foreach (var file in files)
    {
        if (i == 1)
        {
             _eValA = File.ReadLines(file.Name);
            ++i;
        }
        else 
        {
            _eValB = File.ReadLines(file.Name);
            i = 1;

        }
    }
    IEnumerable<String> union = _eValA.Union(_eValB);
    File.WriteAllLines(@"\http\union.txt", union.Cast<String>());
}

But I get this error: Use of unassigned local variable '_eValB, _eValA'

How can I get past it.

Thanks.

Jishan
  • 1,654
  • 4
  • 28
  • 62
  • Initialize to `null` in the declaration if you need to. – sstan Jun 09 '16 at 00:27
  • @sstan I know it may be a duplicate but there are at least a 100 question with a similar premise. The one you pointed doesn't have the exact premise but a similar one. – Jishan Jun 09 '16 at 00:33
  • 1
    It doesn't have to be *exact*. A similar one is perfectly fine, if it points you to the appropriate information. We're not here to solve everyone's specific issue, but to share *knowledge*. It's your responsibility to use that knowledge and apply it to your situation. We don''t need 200 questions like *How do I add two integer variables A & B?*, followed by *How do I add two integer variables B & C? I saw the one about A & B, but my variables are named differently.* – Ken White Jun 09 '16 at 00:47
  • @jeet: Duplicates don't need to be exactly the same, as long as you can apply the principle to your case. Otherwise, because every program out there will always be slightly different from the next, then we'd end up with a question for every possible permutation of the problem, which is probably what is already happening on SO, whether I like it or not (sadly). – sstan Jun 09 '16 at 00:47

2 Answers2

2

The first time through your loop, you will never have both _evalA and _evalB assigned. You need to assign to both to avoid that problem.

There are other related issues. For example, what happens when there aren't exactly two files?

Since there are exactly two files, you shouldn't need to use a loop. If you avoid the loop, you can easily avoid your current issue. For example:

var files = dinfo.GetFiles("*.txt");
System.Collections.Generic.IEnumerable<String> _eValA, _eValB;

// Should really assert that files.Count == 2
_evalA = File.ReadLines(files.First().Name);
_eValB = File.ReadLines(files.Last().Name);

IEnumerable<String> union = _eValA.Union(_eValB);
Paul Hicks
  • 13,289
  • 5
  • 51
  • 78
0

Think about the possible paths that your code could take. It's possible that _eValA may not be initialized, or that _eValB may not be initialized, and thus you would get an error. Since the compiler can detect this, it gives you a compilation error. You need to make sure they get set equal to a value (or null, which lets the compiler know you're taking responsibility for them, as explained here, but note null wouldn't be appropriate in this case because with 0 or 1 files you'd get an ArgumentNullException at the .Union call) before utilizing them. Try:

var _eValA = new string[0];
var _eValB = new string[0];

foreach (var file in files)
{
    if (i == 1)
    {
         _eValA = File.ReadLines(file.Name);
        ++i;
    }
    else 
    {
        _eValB = File.ReadLines(file.Name);
        i = 1;
    }
}

This will ensure they both get initialized before getting used.

Community
  • 1
  • 1
mason
  • 31,774
  • 10
  • 77
  • 121
  • Thanks. Does work. – Jishan Jun 09 '16 at 00:31
  • Why would you create an array instance there? – Evan Trimboli Jun 09 '16 at 01:12
  • @EvanTrimboli Because the eval variables need to be initialized before use. It's true the entire code block shown can be refactored so there's no need for it, but I think it's important to demonstrate specifically why the error was happening and what can be done to satisfy the compiler. – mason Jun 09 '16 at 01:14
  • Agree about the code, but the compiler would be equally satisfied with `IEnumerable _eValA = null;` – Evan Trimboli Jun 09 '16 at 01:16
  • @EvanTrimboli I much prefer creating empty collections over assigning null to collections like that. Let's say we did assign null, and there's no files (or only one file). Then we get an `ArgumentNullException` later at the `.Union` call, when the desired result is probably to continue on with an empty collection. – mason Jun 09 '16 at 01:20
  • I guess what I was getting at is that the compiler doesn't really care if you create an instance or not, your answer seems to imply that the compiler requires you create an instance there, which isn't the case. – Evan Trimboli Jun 09 '16 at 01:25
  • @EvanTrimboli That's true, it doesn't have to be an instance. You can assign null and that explicitly let's the compiler know you're taking responsibility for it, as explained in [this answer](http://stackoverflow.com/a/6213135/1139830). In this case however, assigning null would result in an ArgumentNullException at the Union call when there's 0 or 1 files and therefore would be a poor choice at this particular instance. There may be other situations where assigning null is acceptable. Amended answer to acknowledge this. – mason Jun 09 '16 at 01:37