1

In a UI app I've build, I create a label like this:

    private void InitializeCurrentPerlLabel() {
        currentPerlLabel = new System.Windows.Forms.Label();
        SuspendLayout();

        currentPerlLabel.AutoSize = true;
        currentPerlLabel.Location = new System.Drawing.Point(10, 10);
        currentPerlLabel.Name = "currentPerlLabel";
        currentPerlLabel.Size = new System.Drawing.Size(35, 35);
        currentPerlLabel.TabIndex = 0;
        currentPerlLabel.Font = new Font(Font, FontStyle.Bold);

        Controls.Add(currentPerlLabel);
        Name = "BBUI";
        ResumeLayout(false);
        PerformLayout();
    }

...and I call it simply like this in the constructor: InitializeCurrentPerlLabel().

Now, I'm at the point where I want to automate the creation of various elements. To do so, I will have all the data in a JSON file, will loop over the elements and create them with a build method.

To test, I've got a basic incarnation of the method I'll eventually use to do this, but at this time, I'm just testing a single label. I've changed my code to this:

    private void BuildLabel(string name, Label label) {
        var data = Conf[name];
        label = new System.Windows.Forms.Label();

        SuspendLayout();

        label.AutoSize = data["autosize"];
        label.Location = new System.Drawing.Point(10, 10);
        label.Name = name;
        label.Size = new System.Drawing.Size(35, 35);
        label.TabIndex = 0;
        label.Font = new Font(Font, FontStyle.Bold);

        Controls.Add(label);
        Name = data["name"];
        ResumeLayout(false);
        PerformLayout();       
    }

...and call it like this: BuildLabel("currentPerlLabel", currentPerlLabel);.

It compiles fine, however, I get a System.NullReferenceException: Object reference not set to an instance of an object. error at runtime.

I'm not a fluent C# coder, so could I please get some help as to how I go about setting up my pre-declared currentPerlLabel Label object (through what I would call a reference) in the manner I'm hoping to?

Stack trace:

System.NullReferenceException: Object reference not set to an instance of an object.
   at BBUI.CurrentPerlLabel_Redraw()
   at BBUI.DrawComponents()
   at BBUI.Form1_Load(Object sender, EventArgs e)
   at System.Windows.Forms.Form.OnLoad(EventArgs e)
   at System.Windows.Forms.Form.OnCreateControl()
   at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
   at System.Windows.Forms.Control.CreateControl()
   at System.Windows.Forms.Control.WmShowWindow(Message& m)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.Form.WmShowWindow(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
stevieb
  • 9,065
  • 3
  • 26
  • 36
  • 1
    _"I get a `System.NullReferenceException: Object reference not set to an instance of an object.`"_ Can you include the stack trace and indicate exactly which line is causing the null reference exception. – phuzi Aug 03 '23 at 13:16
  • 1
    Added stack trace – stevieb Aug 03 '23 at 13:20
  • 1
    I know what the exception means, I just don't understand how I get `currentPerlLabel` initialized in the way I'm hoping to. – stevieb Aug 03 '23 at 13:21
  • 1
    The linked duplicate also suggests ways to debug and find the issue. This is something you're going to have to do as we have no idea what `Conf` is. – phuzi Aug 03 '23 at 13:24
  • 2
    Whatever `currentPerLabel` is, the method doesn't do anything with it. The `BuildLabel` method *immediately* re-assigns its local `label` variable to something else and uses that. Perhaps you want to *return* `label` and *assign* that return value to `currentPerLabel` instead? – David Aug 03 '23 at 13:24

1 Answers1

2

Simply add a ref keyword on your label. This means thats the references can be changed, as you are creating a new one.

private void BuildLabel(string name, ref Label label) {
        var data = Conf[name];
        label = new System.Windows.Forms.Label();

        SuspendLayout();

        label.AutoSize = data["autosize"];
        label.Location = new System.Drawing.Point(10, 10);
        label.Name = name;
        label.Size = new System.Drawing.Size(35, 35);
        label.TabIndex = 0;
        label.Font = new Font(Font, FontStyle.Bold);

        Controls.Add(label);
        Name = data["name"];
        ResumeLayout(false);
        PerformLayout();       
    }

Usage :

BuildLabel("currentPerlLabel", ref currentPerlLabel);
Bisjob
  • 567
  • 7
  • 23
  • 1
    This is exactly what I was after. Thank you! Will accept the answer as soon as I'm allowed to. – stevieb Aug 03 '23 at 13:23
  • 2
    though, I would use `out` instead of `ref` when you never use the passed in reference and just overwrite it immediatly – Rand Random Aug 03 '23 at 13:26
  • 4
    Potentially opinion-based, but it may be more clear to *return* `label` and assign that returned value to `currentPerLabel` instead of passing an otherwise not-yet-used variable to the method. The approach here seems to encourage using `ref` as a replacement for `return`, which could lead to some very difficult to maintain code over time. – David Aug 03 '23 at 13:26
  • 1
    yeah return a label would be a cleaner way : `currentPerlLabel = BuildLabel("currentPerlLabel")` Usin out keyword would be more in the case when your method is `TryBuildLabel("currentPerlLabel", out currentPerlLabel)` for example if you can not find the conf fo this label name – Bisjob Aug 03 '23 at 13:28
  • 1
    But if your `currentPerlLabel` is a class member, you won't be able to pass with the out. You would need something like `if (TryBuildLabel("currentPerlLabel", out Label tmpLabel) currentPerlLabel = tmpLabel;` – Bisjob Aug 03 '23 at 13:30