0

I am a newbie and trying to get back in the programming game. Sorry for my ignorance and lack of knowledge as well.

I am trying to see how to fix the return type error message in the code below. I know I can define the variable outside the try block with explicit data type but can that be done for 'var' or any other suggestions.

private IEnumerable GetDirFiles(String location)
{
    try
    {
        //Search all directories for txt files
        var emailfiles = Directory.EnumerateFiles(location, "*.txt", SearchOption.AllDirectories);
    }
    catch(Exception ex)
    {
        Console.WriteLine("Message for admins: " + ex.Message);
    }
    finally
    {
        textBox1.Clear();
        var emailfiles = Directory.EnumerateFiles(location, "*.msg", SearchOption.AllDirectories);
    }

    return emailfiles;
}

The error message is "emailfiles does not exist in the current context" which I understand as to why because it is being defined in the try block.

Thanks.

Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68
dbss
  • 17
  • 1
  • You can use `dynamic` if you want to initialize it with nothing – Lyco Aug 03 '18 at 18:12
  • 4
    Why, why would you suggest that – BradleyDotNET Aug 03 '18 at 18:13
  • The try block creates a new scope – James Parsons Aug 03 '18 at 18:15
  • 2
    You should understand that, the way you've written it, regardless of whether the call to `Directory.EnumerateFiles()` in the `try` succeeds, because you call it again in `finally` (which is always executed) by the end of the method `emailFiles` will only ever contain the result of the second call to `Directory.EnumerateFiles()`. Also, if something in the `finally` block should throw an exception, it won't be caught within `GetDirFiles()`. – Lance U. Matthews Aug 03 '18 at 18:23
  • 1
    none of these answers are correct imo. Whether or not `var emailfiles = Directory.EnumerateFiles(location, "*.txt", SearchOption.AllDirectories);` succeeds, the code in the finally block will always be executed, and the returned value will be `var emailfiles = Directory.EnumerateFiles(location, "*.msg", SearchOption.AllDirectories);` – Adam Vincent Aug 03 '18 at 18:27
  • jinx @BACON, you owe me a coke – Adam Vincent Aug 03 '18 at 18:27
  • @AdamVincent That's a good catch, but its not actually what the question is asking :) I'll put in an aside though so its noted in an answer. – BradleyDotNET Aug 03 '18 at 18:28
  • Possible duplicate of [Declare a var without initializing it... just yet](https://stackoverflow.com/questions/28717397/declare-a-var-without-initializing-it-just-yet) – Lance U. Matthews Aug 03 '18 at 18:30

6 Answers6

5

Yes, you need to declare emailFiles outside the block, and no var will not work (without some gymnastics).

var requires an assignment because its using implicit typing. Without a value there is nothing to get the type from.

Your only other alternative would be to return from the try and catch blocks, rather than at the end of the method.

As @AdamVincent notes you have a bigger problem; which is that because a finally block always executes (regardless of exceptions or lack thereof) the return value will always actually be Directory.EnumerateFiles(location, "*.msg", SearchOption.AllDirectories). You probably meant for that to be in the catch block.

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
0

Just don't use var. Figure out what type is returned from Directory.EnumerateFiles (probably System.Collections.Generic.IEnumerable). That's the only type you are setting emailfiles to anyway. Then you can just initialize it like:

(whatever-type) emailfiles;

Outside the try block.

0

In this scenario, you can just return from the try or finally as suggested in other answers. but if you have more operations to perform in try or finally then, you can declare the object outside of try block like below.

private IEnumerable GetDirFiles(String location)
{
    IEnumerable<string> emailfiles; // just declare the variable outside try..catch scope.
    try
    {
        //Search all directories for txt files
        emailfiles = Directory.EnumerateFiles(location, "*.txt", SearchOption.AllDirectories);
        // any other operations on emailfiles goes here
    }
    catch(Exception ex)
    {
        Console.WriteLine("Message for admins: " + ex.Message);
    }
    finally
    {
        textBox1.Clear();
        emailfiles = Directory.EnumerateFiles(location, "*.msg", SearchOption.AllDirectories);
    // any other operations on emailfiles goes here
    }
    return emailfiles;
}
Vinit
  • 2,540
  • 1
  • 15
  • 22
0

Since you don't need to do anything in this method with the results of your EnumerateFiles calls, just return the results directly for brevity:

private IEnumerable GetDirFiles(String location)
{
    try
    {
        //Search all directories for txt files
        return Directory.EnumerateFiles(location, "*.txt", SearchOption.AllDirectories);
    }
    catch(Exception ex)
    {
        Console.WriteLine("Message for admins: " + ex.Message);
    }        
    finally
    {
        textBox1.Clear();
        return Directory.EnumerateFiles(location, "*.msg", SearchOption.AllDirectories);
    }
}

If you would happen to need to do something with the list of files before returning, you'd have to define your variable outside of the try..catch block specifying the type like so:

private IEnumerable GetDirFiles(String location)
{
    IEnumerable<string> emailfiles;
    try
    {
        //Search all directories for txt files
        emailfiles = Directory.EnumerateFiles(location, "*.txt", SearchOption.AllDirectories);
    }
    catch(Exception ex)
    {
        Console.WriteLine("Message for admins: " + ex.Message);
    }        
    finally
    {
        textBox1.Clear();
        emailfiles = Directory.EnumerateFiles(location, "*.msg", SearchOption.AllDirectories);
    }

    // now do something with emailfiles
    return emailfiles;
}

Hope this helps!

Jon
  • 569
  • 2
  • 11
0
private IEnumerable<string> GetDirFiles(String location)
{
    IEnumerable<string> emailfiles = Enumerable.Empty<string>();
    try
    {
        //Search all directories for txt files
        emailfiles = Directory.EnumerateFiles(location, "*.txt", SearchOption.AllDirectories);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Message for admins: " + ex.Message);
    }
    finally
    {
        textBox1.Clear();
        emailfiles = Directory.EnumerateFiles(location, "*.msg", SearchOption.AllDirectories);
    }

    return emailfiles;
}

You also forgot to return type of IEnumerable you want to return

artista_14
  • 674
  • 8
  • 22
0

I hope the changes below are don't confuse you too much. I've changed IEnumerable to IEnumerable<string> to get access to LINQ methods. In this case .Any() to see if the GetTextFiles() had any results. If GetTextFiles() returns no results, it will return GetEmailFiles(). If either throws an exception it will be caught. Lastly, no matter the outcome your textbox will be cleared.

private IEnumerable<string> GetDirFiles(string location)
{
    IEnumerable<string> result;
    try
    {
        result = GetTextFiles(location).ToList(); //Added .ToList() to avoid multiple enumerations.

        if (!result.Any())
        {
          result = GetMsgFiles(location);
        }

    }
    catch(Exception ex)
    {
        Console.WriteLine("Message for admins: " + ex.Message);
    }
    finally
    {
        textBox1.Clear();
    }

    return result;
}

private IEnumerable<string> GetTextFiles(string location)
{
    return Directory.EnumerateFiles(location, "*.txt", SearchOption.AllDirectories);
}

private IEnumerable<string> GetMsgFiles(string location)
{
    return Directory.EnumerateFiles(location, "*.msg", SearchOption.AllDirectories);
}
Adam Vincent
  • 3,281
  • 14
  • 38