0

I am sitting here finding myself writing a recursive call for C# to write a RegistryKey.

This is something I could hard code easily enough, but I'd to do it recursively.

using System;
using System.Collections.Generic;
using Microsoft.Win32;

private const string regKeyPath = @"Software\Apps\jp2code\net\TestApp";

static void Main() {
  string[] split = regKeyPath.Split('\\');
  RegistryKey key = null;
  try {
    keyMaker(Registry.LocalMachine, split);
  } finally {
    if (key != null) {
      key.Close();
    }
  }
  // continue on with Application.Run(new Form1());
}

So, keyMaker is what I want to be my recursive function.

private static void keyMaker(RegistryKey key, string[] path) {
  string subKey = null;
  string[] subKeyNames = key.GetSubKeyNames();
  foreach (var item in subKeyNames) {
    if (path[0] == item) {
      subKey = item;
    }
  }
  RegistryKey key2 = null;
  try {
    if (String.IsNullOrEmpty(subKey)) {
      key2 = key.CreateSubKey(subKey);
    } else {
      key2 = key.OpenSubKey(subKey);
    }
    keyMaker(key2, &path[1]); // <= NOTE! Not allowed/defined in C#
  } finally {
    key2.Close();
  }
}

So, I can't simply pass the array starting with the next element of the array.

Is there a neat way to do this in C#?

The Registry bit has nothing to do with the problem but to add my real world problem to an array task.

1
  • not sure if it's beneficial to you, but there is a class called ArraySegment that you could use to pass the remainder of the path array (without allocating new arrays, and allows you to get back to the original) Commented Jan 11, 2012 at 22:44

4 Answers 4

3

A simple way to be to change your method's signature to include the starting index:

void keyMaker(RegistryKey key, string[] path, int startIndex)

Apart from that, you can use a LinkedList<T> or a Queue<T> instead of an array, and use LinkedList<T>.RemoveFirst() or Queue<T>.Dequeue() methods to remove their head elements.

But you don't need recursion to solve this at all (unless this is an exercise).

Sign up to request clarification or add additional context in comments.

2 Comments

It is only an exercise in that I did not see a way to do this using string[] array. I never thought of LinkedList<T> or Queue<T>. Good ideas!
K.I.S.S. - I just added the index value.
1

Don't do it recursively is all. Here's how I'd write it, given that a key is simply returned by CreateSubKey if it exists:

private static void keyMaker(RegistryKey key, string[] path) {
    foreach(string subkey in path) {
        key = key.CreateSubKey(subkey);
    }
}

If closing them immediately is important (I doubt it):

private static void keyMaker(RegistryKey key, string[] path) {
    RegistryKey lastKey = key;

    foreach(string subkey in path) {
        key = key.CreateSubKey(subkey);
        lastKey.Close();
        lastKey = key;
    }

    lastKey.Close();
}

1 Comment

I like this. It might be the way I go, so don't change it. Still, I'm curious how to pass an array, given an array.
1

Although I'd prefer passing the index like @Groo suggested, another possibility is to use an IEnumerable<string> instead of a string[] and use LINQ. In the recursive call, you could pass path.Skip(1), which will remove the first element from the list (or, more precisely, return a new IEnumerable<string> which starts on the second element).

1 Comment

LINQ - I always enjoy finding a place to try out some of that!
1

Editted in response to LOL.

keyMaker(Registry.LocalMachine, ref split, 0);
....
private static void keyMaker(RegistryKey key, ref string[] path, int index) {
if( index > path.length - 1 ) return;
....
if (path[index] == item) {
....
keyMaker(key2, ref path, ++index);
....

2 Comments

LOL - you used the illegal &path in your call to keyMaker, but I understand what you meant by the index.
You don't need to use ref. A reference is passed regardless.

Your Answer

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