0

I am kind of confused here . I have a program that has been running for years , Just yesterday when i made some few changes in one part of the file. It begin throwing "NullReferenceException" on ref string method.

   string message = "";

   this.GetAuditMessage(grpAccess, ref message);


    private void GetAuditMessage(Control c_parent, ref string message)
    {
        foreach(Control c in c_parent.Controls) 
        {       
            Console.WriteLine(c.Name);
            if (c.GetType().ToString().Equals("System.Windows.Forms.Panel"))
            {
                try
                {
                    string str = message;
                    GetAuditMessage(c, ref str);
                }
                catch(Exception nu) 
                {
                    Console.WriteLine(nu.InnerException.ToString());
                }


            }
            else if (c.GetType().ToString().Equals("System.Windows.Forms.TextBox") ||
                c.GetType().ToString().Equals("System.Windows.Forms.ComboBox"))
            {
                int n = c.Tag.ToString().IndexOf(":");
                int len = c.Tag.ToString().Length;

                string controlName = c.Tag.ToString().Substring(0, n);
                string oldSetting = c.Tag.ToString().Substring(n + 1, len - (n + 1));

                if (!oldSetting.Equals(c.Text))
                {
                    message += "Change " + controlName + "' from '" + oldSetting + "' to '" + c.Text + ".'\n";
                }
            }
        }
    }

When i put a break at GetAuditMessage(c, ref message) . It throws exception . However, i modify to something like below.

string str = message;
GetAuditMessage(c, ref str);

The above works fine. I then try and run the old version . It run fine with no exception. Please can some one explain why the exception ? Please why does it throw now and doesn't before ? How do i best fix this ?

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
Nuru Salihu
  • 4,756
  • 17
  • 65
  • 116
  • 2
    What line throws the exception? What value is `null`? – Jeroen Vannevel Oct 27 '14 at 08:07
  • What is in `........` code? –  Oct 27 '14 at 08:07
  • [What is a NullReferenceException and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Soner Gönül Oct 27 '14 at 08:08
  • are you sure it's because of `ref message`? – Rahul Oct 27 '14 at 08:08
  • Hi, please above is the complete method. I want message to change according to the control type. Hence i first pass it as null . Please see the metohd. – Nuru Salihu Oct 27 '14 at 08:12
  • btw; your `if` tests could just be `if(c is Panel)` / `else if(c is TextBox || c is ComboBox)` – Marc Gravell Oct 27 '14 at 08:12
  • your question lacks vital info to figure out what's wrong since you say above works fine but you don't show the non working code? Hence i think http://msdn.microsoft.com/en-us/library/y740d9d3.aspx should help you find it out – Dbl Oct 27 '14 at 08:13
  • Sorry guys for the question. Was too tensed and confused. Like Marc said below, it turns out i didnt set the tag property as marc mentioned. – Nuru Salihu Oct 27 '14 at 08:52

1 Answers1

2

My best guess here is that one of the c.Tag is null, or not quite in the expected format - and your "fix" is unrelated (although it does stop it working correctly). You would do better to pass in a StringBuilder, btw, and use that to build up the composed string; no need for ref then.

It doesn't help that your catch block also does something careless, by accessing .ToString() on something that could be null - i.e. InnerException. So; if we assume that some Tag is not a string or not in the expected format: it would throw either a NullReferenceException or an ArgumentOutOfRangeException, without an InnerException; your catch block, if it is hit (i.e. if this isn't the outermost control - the form itself), would in turn throw a NullReferenceException.

If it was me:

var sb = new StringBuilder();
this.GetAuditMessage(grpAccess, sb);
var message = sb.ToString();


private void GetAuditMessage(Control c_parent, StringBuilder sb) {
    foreach(Control c in c_parent.Controls)  {       
        Console.WriteLine(c.Name);
        if (c is System.Windows.Forms.Panel) {
            try {
                GetAuditMessage(c, sb);
            } catch(Exception nu)  {
                Console.WriteLine(nu.Message);
            }
        }
        else if (c is System.Windows.Forms.TextBox ||
            c is System.Windows.Forms.ComboBox)
        {
            string tag = c.Tag == null ? "" : c.Tag.ToString();
            int n = tag.IndexOf(":");
            if(n < 0) continue;
            int len = tag.Length;

            string controlName = tag.Substring(0, n);
            string oldSetting = tag.Substring(n + 1, len - (n + 1));

            if (!oldSetting.Equals(c.Text))
            {
                sb.AppendFormat("Change {0} from '{1}' to '{2}'.",
                    controlName, oldSetting, c.Text).AppendLine();
            }
        }
    }
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Hi, Marc, You are indeed right , It turns out i added a control and didnt set the tag property as i did for other individual controls. Btw, please i am curious about that your sb solution. I mean can we use stringBuilder in that way ? Just like a reference parameter ? If so then , can i conclude that i can use stringBuilder in a place of ref parameter ? If not please what are the differences btw the two tearms ? – Nuru Salihu Oct 27 '14 at 08:51
  • @Nuri keep in mind that `string` is immutable; the way you are using `ref string` here is so that when you (repeatedly) create a *new* string (by concatenating others), that new string is visible to the call-site. `StringBuilder`, by contrast, is a mutable mechanism for composing strings. Because it is mutable, there is never a need to change the reference, hence no `ref`. It is also much, much cheaper, as it avoids the need to create (and later: collect) all of the intermediate strings. – Marc Gravell Oct 27 '14 at 08:59
  • thanks . think the mutable and immutable mechanisms explained above cleared my confusion. In my code above, i use ref because i need to concatenate only. I do not need to create new string or modify. If need to modify or create new then will adopt the stringBuilder mechanism for its mutable. Am i right? Either way , your explanation helps alot. Thnks. – Nuru Salihu Oct 27 '14 at 10:14