• Welcome to TechPowerUp Forums, Guest! Please check out our forum guidelines for info related to our community.

Sample C# Code : Fun with Generics for single form instances

Kreij

Senior Monkey Moderator
Joined
Feb 6, 2007
Messages
13,817 (2.20/day)
Location
Cheeseland (Wisconsin, USA)
Ok, if you read my post on Single instance forms (if you haven't read that post its HERE), you are probably thinking, "Kreij, I have a launcher bar with ten buttons that open ten forms. That would be a buttload of redundant coding !! Isn't there a better way ?"

Well there sure is a better way. Use Generics.
Generics let you create classes and methods that take variable Types.

Variable type classes are declared like this ... class Class1<T>
Where the "T" will be replaced by the type you instantiate the class with (ie. string, int, Form, etc).
It can also take qualifiers for the class types (ie. Form, new() )

So the class declaration "class Class1<T> where T : Form, new()" tells the compiler that the "T" must be of a "Form" type that has its own constructor (the new())

So what do you do ...

First create a class that will handle generic forms

Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication2
{
    class Class1<T> where T : Form, new()
    {
        private static T mInst;

        public Class1()
        {
            // Here i am just stuffing our single form instance code
            //  into the class constructor
            if (mInst == null)
            {
                mInst = new T();
                mInst.Show();
            }
            else
            {
                mInst.WindowState = FormWindowState.Normal;
                mInst.Focus();
            }
        }

        // You need this method for when a form closes
        public void letGo()
        {
            mInst = null;
        }
    }
}

Now instead of having to modify each form's codefile to make sure it handles singular instances, all you have to do is call the generic class and it will make sure the single instance is managed and call the form constructor for you.

In the following example, I have created a form (Form1) that has 2 buttons (button1 and button2).
Each button opens another form (Form2 and Form3).
I did not include the code for Form2 and Form3 as they are just empty forms with no controls or anything. This is just proof of concept coding ;)

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // create an instance of class1 that will create a Form2 instance
            Class1<Form2> temp = new Class1<Form2>();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            // create an instance of class1 that will create a Form3 instance
            Class1<Form3> temp = new Class1<Form3>();
        }
    }
}

As you can see, from your main form you do not have to instantiate the other forms or call any methods or properties on the forms to get the same functionality as my initial post on single form instances. You just have to create an instance of the generic class for any form you want to make.

I gotta admin, C# has some pretty slick features ...

Comments or questions are welcome :)

Edit :

Oops, I forgot about a little clean up ...

In your form code files that the generic class calls you still must have a way of nulling out the "mInst" value so that the generic class can recreate the form if you have closed it.

So, without ado, here is the OnClose call for "Form2" ...

Code:
protected override void OnClosed(EventArgs e)
        {
            Class1<Form2> temp = new Class1<Form2>();
            temp.letGo();
            base.OnClosed(e);
        }
 
Last edited:

Kreij

Senior Monkey Moderator
Joined
Feb 6, 2007
Messages
13,817 (2.20/day)
Location
Cheeseland (Wisconsin, USA)
Ok, I found an even better way of doing this ...

Instead of putting the single form instance code in the generic class constructor, we will make the constructor private and use a public static method (CreateInst) to instantiate the form. We will also make the letGo() method static.

Like so ...

Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication2
{
    class Class1<T> where T : Form, new()
    {
        private static T mInst;

        public Class1()
        {
        }

        public static void CreateInst()
        {
            if (mInst == null)
            {
                mInst = new T();
                mInst.Show();
            }
            else
            {
                mInst.WindowState = FormWindowState.Normal;
                mInst.Focus();
            }
        }

        public static void letGo()
        {
            mInst = null;
        }
    }
}

Now we do not have to use the "new" method to use this class's methods at all.
So to create a single instance form you can just use ..

Code:
private void button1_Click(object sender, EventArgs e)
        {
            Class1<Form2>.CreateInst();
        }

To clean up we also only need one extra line instead of two.

Code:
        protected override void OnClosed(EventArgs e)
        {
            Class1<Form2>.letGo();
            base.OnClosed(e);
        }

Sorry about that. I wasn't happy with the original.
No wonder it takes me so long to write code, I am forever trying to make it more compact and efficient. :)
 
Joined
Jul 1, 2005
Messages
5,197 (0.76/day)
Location
Kansas City, KS
System Name Dell XPS 15 9560
Processor I7-7700HQ
Memory 32GB DDR4
Video Card(s) GTX 1050/1080 Ti
Storage 1TB SSD
Display(s) 2x Dell P2715Q/4k Internal
Case Razer Core
Audio Device(s) Creative E5/Objective 2 Amp/Senn HD650
Mouse Logitech Proteus Core
Keyboard Logitech G910
Wait.. so this makes a form...?

Theres a non Visual studio C# compiler?

Nifty.

Would be awesome to see a C# program void of microsofts .net crap.
 

Kreij

Senior Monkey Moderator
Joined
Feb 6, 2007
Messages
13,817 (2.20/day)
Location
Cheeseland (Wisconsin, USA)
No, this is using VC# Express from Microsoft.
 

Napoleon_5

New Member
Joined
Jan 15, 2009
Messages
1 (0.00/day)
Hi

I tested this code in my App and it show the form without troubles. But when I close and try to open (show) it again, it does not work. I May not use the OnClosed method the right way. I put this method in my child form and called it from my Form1_FormClosed(...) method.

Would you please help me with this?

IB
 

FordGT90Concept

"I go fast!1!11!1!"
Joined
Oct 13, 2008
Messages
26,259 (4.63/day)
Location
IA, USA
System Name BY-2021
Processor AMD Ryzen 7 5800X (65w eco profile)
Motherboard MSI B550 Gaming Plus
Cooling Scythe Mugen (rev 5)
Memory 2 x Kingston HyperX DDR4-3200 32 GiB
Video Card(s) AMD Radeon RX 7900 XT
Storage Samsung 980 Pro, Seagate Exos X20 TB 7200 RPM
Display(s) Nixeus NX-EDG274K (3840x2160@144 DP) + Samsung SyncMaster 906BW (1440x900@60 HDMI-DVI)
Case Coolermaster HAF 932 w/ USB 3.0 5.25" bay + USB 3.2 (A+C) 3.5" bay
Audio Device(s) Realtek ALC1150, Micca OriGen+
Power Supply Enermax Platimax 850w
Mouse Nixeus REVEL-X
Keyboard Tesoro Excalibur
Software Windows 10 Home 64-bit
Benchmark Scores Faster than the tortoise; slower than the hare.
If you .Close() a form, it can't be retreived. You have to create a new instance and start from the beginning. If you .Show() and .Hide(), the original object is still there--just not visible. Probably you'd be better off reinstantiating the Form/object that was closed for the sake of reducing the memory footprint. The quickest way to do that is to save all the variables in a parent scope for recalling. Taking the time to code that also has the added benefit of making it easier to code save/load functions for users to begin where they left off. So, for instance, if they closed a form, then the whole app, they could start the app and then the form and be exactly where they left it.


@op: They aren't "generics." What you are doing is "strongly typing." You probably know that now seeing how hold this thread is. XD
 
Top