locked
Recursive function VB to C# RRS feed

  • Question

  • Hello I'm using vb 2010 and I usually write in vb.net, but currently I've been diving into C# and I'm having trouble converting one of my functions. Can you help me out?

     Function GetDirectories(ByVal StartPath As String, DirectoryList As ArrayList)
            Dim Dirs() As String = Directory.GetDirectories(StartPath)
            DirectoryList.AddRange(Dirs)

            For Each Dir As String In Dirs
                GetDirectories(Dir, DirectoryList)
                On Error Resume Next
            Next
        End Function

    I've tried this but I'm not really getting the results I want...

    public void GetDirectories(string startPath)
            {
                ArrayList newDirs = new ArrayList();

                string[] dirs = Directory.GetDirectories(startPath);
                newDirs.AddRange(dirs);

                 foreach(String dir in dirs)
                 {
                     DirList.Add(dir);
                     GetDirectories(dir);

                 }
            }

    Friday, May 31, 2013 12:53 AM

Answers

  • John Wein's answer, but changed to a 'void' method, is correct - the original VB code was incorrectly coded as a function which didn't return anything (it's amazing what VB lets you get away with):

    public void GetDirectories(string StartPath, ArrayList DirectoryList)
    {
        string[] Dirs = Directory.GetDirectories(StartPath);
        DirectoryList.AddRange(Dirs);
        try
        {
            foreach (string Dir in Dirs)
                GetDirectories(Dir, DirectoryList);
        }
        catch { }
    }


    Convert between VB, C#, C++, & Java (http://www.tangiblesoftwaresolutions.com)
    Instant C# - VB to C# Converter
    Instant VB - C# to VB Converter


    Friday, May 31, 2013 3:16 PM

All replies

  • Why did you remove the DirectoryList parameter? It is essential to building the result for your recursion.

    Try doing a straight line-by-line translation (except for that 'On Error Resume Next' - you should translate that into a try with an empty catch around the Directory.GetDirectories)


    Paul Linton

    Friday, May 31, 2013 1:01 AM
  • No need for a function (either in C# or VB.Net) simply use GetDirectories overload with a SearchOption set on AllDirectories or same thing with EnumerateDirectories for deferred lazy evaluation.

    ref:
    http://msdn.microsoft.com/en-us/library/ms143314.aspx
    http://msdn.microsoft.com/en-us/library/dd383462.aspx

    Forgive my writing, English isn't my native language.

    • Proposed as answer by PaulLinton Friday, May 31, 2013 1:07 AM
    Friday, May 31, 2013 1:05 AM
  • No need for a function (either in C# or VB.Net) simply use GetDirectories overload with a SearchOption set on AllDirectories or same thing with EnumerateDirectories for deferred lazy evaluation.

    ref:
    http://msdn.microsoft.com/en-us/library/ms143314.aspx
    http://msdn.microsoft.com/en-us/library/dd383462.aspx

    Forgive my writing, English isn't my native language.

    You can use the following code block

    Directory.GetDirectories(StartPath,  "*.*", SearchOption.AllDirectories);

     


    Muthukrishnan Ramasamy
    net4.rmkrishnan.net
    Use only what you need, Reduce global warming


    Friday, May 31, 2013 5:15 AM
  • try this

    public object GetDirectories(string StartPath, ArrayList DirectoryList) { string[] Dirs = Directory.GetDirectories(StartPath); DirectoryList.AddRange(Dirs); foreach (string Dir in Dirs) {

    try{ GetDirectories(Dir, DirectoryList); // ERROR: Not supported in C#: OnErrorStatement

    // this on error functionality can be achieved by placing try/catch

    //block around your code

    }catch(){} } }


    conversion tool

    http://www.developerfusion.com/tools/convert/vb-to-csharp/


    Faisal Ahmed Farooqui —————————— If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Friday, May 31, 2013 7:20 AM
  • Hello I tried your suggestion, and this is what I ran into before... I'm getting an error "not all code paths return a value" since I'm not returning outside of the foreach. Is there a way around this?
    Friday, May 31, 2013 11:27 AM
  • I ended up getting removing it because I kept getting not all paths return a value when trying to return the value like I am in vb. So I cut that out of the function and created the newDirs to act as the same thing.
    Friday, May 31, 2013 11:34 AM
  • This one seems to be working, however I'll have to look at it more closely when I get home this after noon.
    Friday, May 31, 2013 11:35 AM
  • void functions cannot give a "not all code paths return a value" Compilation errors, ever. Only non-void functiosn can. The problem is someplace else in your code. You propably forgot a closing bracket or two in the code above this. Or the problem is in the Code where you try to call this recursive function.


    Let's talk about MVVM: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/b1a8bf14-4acd-4d77-9df8-bdb95b02dbe2


    Friday, May 31, 2013 11:38 AM
  • When I past this:

    public object GetDirectories(string StartPath, ArrayList DirectoryList) { string[] Dirs = Directory.GetDirectories(StartPath); DirectoryList.AddRange(Dirs); foreach (string Dir in Dirs) {

    try{ GetDirectories(Dir, DirectoryList); // ERROR: Not supported in C#: OnErrorStatement

    // this on error functionality can be achieved by placing try/catch

    //block around your code

    }catch(){} } }

    Which I get the error as well. I changed my function to be a void due to me getting that error so currently do not get it.

    Friday, May 31, 2013 11:46 AM
  • This is not a void function. This is a function that return an object.

    And so the compiler is telling you: "Hey, you told me this would return an object. So where the hell is the return or throw exception statement?"

    Exceptions are a sort of return value, wich is why Interface Functions with return values are autocreated with syntax similar to this:

    throw new NotSupportedException();

    Having this one line autocreated means adding a Interface will not break the class.


    Let's talk about MVVM: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/b1a8bf14-4acd-4d77-9df8-bdb95b02dbe2

    Friday, May 31, 2013 11:51 AM
  • Try this

    public List<string> GetDirectories(string StartPath) {
    	var lstDirs = new List<string>();
    	GetDirectories(StartPath, lstDirs);
    	return lstDirs;
    }
    public void GetDirectories(string StartPath, List<string> DirectoryList) {
    	string[] Dirs;
    	try {
    		Dirs = Directory.GetDirectories(StartPath);
    		DirectoryList.AddRange(Dirs);
    	} catch {
    		return;
    	}
    	foreach (string Dir in Dirs)
    		GetDirectories(Dir, DirectoryList);
    }


    Muthukrishnan Ramasamy
    net4.rmkrishnan.net
    Use only what you need, Reduce global warming

    Friday, May 31, 2013 12:09 PM
  • Hello,

    It's better to use Directory.EnumerateDirectories(...) than Directory.GetDirectories(...) especially over a lot of directories.

    Another thing to mention is that you better use a local stack than traditional recursions that fills the call stack.

    So I'd do something like this if I was to do it manually.

    public static IEnumerable<DirectoryInfo> GetDirectories(string path)
    		{
    			Stack<DirectoryInfo> stack = new Stack<DirectoryInfo>();
    
    			stack.Push(Directory.CreateDirectory(path));
    
    			while (stack.Count > 0)
    			{
    				DirectoryInfo currentDirectory = stack.Pop();
    
    				foreach (var directory in currentDirectory.EnumerateDirectories())
    				{
    					bool isReparsePoint = (directory.Attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint;
    
    					if (!isReparsePoint)
    					{
    						stack.Push(directory);
    
    						yield return directory;
    					}
    				}
    			}
    		}
    


    Regards,

    Eyal Shilony

    Friday, May 31, 2013 12:47 PM
  • This should give the same results as your VB code:

        public object GetDirectories(string StartPath, ArrayList DirectoryList)
        {
          
    string[] Dirs = Directory.GetDirectories(StartPath);
          DirectoryList.AddRange(Dirs);
          
    try
          {
            
    foreach (string Dir in Dirs)
              GetDirectories(Dir, DirectoryList);
          }
          
    catch { }
          
    return null;
        }
    Friday, May 31, 2013 2:44 PM
  • John Wein's answer, but changed to a 'void' method, is correct - the original VB code was incorrectly coded as a function which didn't return anything (it's amazing what VB lets you get away with):

    public void GetDirectories(string StartPath, ArrayList DirectoryList)
    {
        string[] Dirs = Directory.GetDirectories(StartPath);
        DirectoryList.AddRange(Dirs);
        try
        {
            foreach (string Dir in Dirs)
                GetDirectories(Dir, DirectoryList);
        }
        catch { }
    }


    Convert between VB, C#, C++, & Java (http://www.tangiblesoftwaresolutions.com)
    Instant C# - VB to C# Converter
    Instant VB - C# to VB Converter


    Friday, May 31, 2013 3:16 PM
  • Wow thanks for all the feedback. I wish I could try them all out now, but I'll have to wait until I get home.
    Friday, May 31, 2013 3:29 PM
  • Hello there,

    I tried out Directory.GetDirectories(StartPath, "*.*",SearchOption.AllDirectories); Which worked great. However, there are certian placeses that it does not like to go or does not have access to search such as if I search the C: drive, so it looking like I need to use the funtion based search for this to dive deeper into a directory. I havent tested out the equivalent of the function yet, but when I do I'll let you know how that one goes to. Thanks for the help!

    Monday, June 3, 2013 11:23 AM
  • Hello I've tried the following:

    public void GetDirectories(String StartPath, ArrayList DirectoryList)
            {
                String[] Dirs = Directory.GetDirectories(StartPath);
                DirectoryList.AddRange(Dirs);
                try
                {
                    foreach (string Dir in Dirs)
                    {
                        GetDirectories(Dir, DirectoryList);
                    }
                }
                catch { }
            }

    Which Works... however It doesn't go as deep as I'd like, somehow it's treated different then my original function below.

    Function GetDirectories(ByVal StartPath As String, DirectoryList As ArrayList)
            Dim Dirs() As String = Directory.GetDirectories(StartPath)
            DirectoryList.AddRange(Dirs)

            For Each Dir As String In Dirs
                GetDirectories(Dir, DirectoryList)
                On Error Resume Next
            Next
        End Function

    If I search one of my test paths with the C# functions It comes back with 424 folders, but if I scan using the vb function it comes back with 1751 which is right. I'm not sure if it's due to the on error resume next or not. But I believe that's what the try catch was supposed to act like right? I'm not sure what else I'm missing here???

    Sunday, June 9, 2013 3:03 AM
  • Ha, well I just figured it out.... If I put the try cach inside the foreach loop then it returns the correct number of foldres in my test path. Thanks everyone for your help, hopfully I'll become a greate C# coder and pass on this Knoledge.
    Sunday, June 9, 2013 3:06 AM
  • Good catch about moving the try/catch - it makes sense to have it within the 'foreach'.

    Convert between VB, C#, C++, & Java (http://www.tangiblesoftwaresolutions.com)
    Instant C# - VB to C# Converter
    Instant VB - C# to VB Converter

    Sunday, June 9, 2013 3:12 AM
  • Good catch about moving the try/catch - it makes sense to have it within the 'foreach'.

    Why it makes sense? in some IO operations you're right it might make sense but in this case it doesn't make sense at all, he probably has reparse points or something that wasn't handled and he just swallowed the exception when he actually could handle it or better yet prevent it from  happening.


    Regards,

    Eyal Shilony

    Sunday, June 9, 2013 5:41 AM
  • Either outside or inside the foreach loop is the wrong place for the try/catch.  The actual loop is not going to throw an exception.  Calling this GetDirectories method is not what throws the exception.  The exception is thrown by Directory.GetDirectories and that is what you need to protect with your try/catch.

    It will only make a difference if the initial value of StartPath is an unreachable directory.  But if you are trying to ignore unreachable directories then that is where the try/catch needs to go.


    Paul Linton

    Sunday, June 9, 2013 6:52 AM
  • "Why it makes sense?"

    "Either outside or inside the foreach loop is the wrong place for the try/catch."

    To convert the VB code to C# code, the try/catch needs to be inside the loop. 

    Sunday, June 9, 2013 7:04 AM
  • You are correct. To convert the buggy VB to buggy C# you need the try/catch inside the loop.

    Paul Linton

    Sunday, June 9, 2013 11:12 AM