Fundamentals of Generic Classes

Introduction

Like a function, a class can be created as a generic one. When a class is created as generic, it is asked to process a value without knowing what type that value is. This means that the class will know the type of value only when its object is accessed.

Introduction to Creating a Generic Class

To create a generic class, on the right side of the name of the class, type the <> operator and enter a name for the parameter type. Here is an example:

public class Generator<TypeOfValue>
{
}

This parameter type is just a representative of a data type. As a data type, you can use it to declare a variable in the body of the class. Here is an example:

public class Generator<TypeOfValue>
{
    public TypeOfValue value;
}

After declaring such a variable, you can use it in your project. For example, you can access it outside the class using the period operator. Inside the class, one way you can use the variable is to involve it in an expression in one of the methods of the class. Here is an example:

public class Generator<TypeOfValue>
{
    public TypeOfValue Value;

    public string Show()
    {
        return Value.ToString();
    }
}

Using a Generic Class

After creating a generic class, you can use it. One way to do this, as we have learned previously, consists of declaring a variable of the class. If the class is a generic one, on the right side of its name when declaring the variable, type the <> operator. Inside this operator, enter the data type that will be processed as the parameter type of the generic class. Here is an example:

Generator<int> gen = new Generator<int>();

You can also declare a variable of a generic type using the var or the dynamic keyword. To do this, use var or dynamic on the left side of the variable name, omit the <> operator and the data type. Here are examples:

Generator<int> gen = new Generator<int>();

var calculation = new Generator<int>();
dynamic expression = new Generator<int>();

After declaring the variable (whether using the name of the class or the var or the dynamic keyword), you can then access the member(s) of the class using the period operator. Here are examples:

using static System.Console;

Title = "Generic Vaplues";
WriteLine("Generic Values");
WriteLine("------------------------------------");

Generator<int> gen = new Generator<int>();
var calculation = new Generator<char>();
dynamic expression = new Generator<double>();

WriteLine("A Value: {0}", gen.Value);
WriteLine(string.Format("A Calculation: {0}", calculation.Value));
WriteLine($"An Expression: {expression.Value}");
            
WriteLine("=======================================");
            
public class Generator<TypeOfValue>
{
    public TypeOfValue Value;

    public string Show()
    {
        return Value.ToString();
    }
}

This would produce:

Generic Values
------------------------------------
A Value: 0
A Calculation:
An Expression: 0
=======================================
Press any key to close this window . . .

Passing a Parameter Type to a Method

We saw that you could declare a variable of a parameter type in a generic class. Another way you can use a parameter type is to add a parameter to a method and make that parameter a parameter type. As seen previously, you can ignore or use the parameter. For example, you can display its value to the user. Here is an example:

using static System.Console;

Title = "Generic Vaplues";
WriteLine("Generic Values");
WriteLine("----------------");

var iValue = 246;
Generator<int> gen = new Generator<int>();

gen.Show(iValue);

char cValue = 'G';
var calculation = new Generator<char>();
calculation.Show(cValue);

double nbr = 355.65;
dynamic expression = new Generator<double>();
expression.Show(nbr);

WriteLine("=================================");

public class Generator<TypeOfValue>
{
    public void Show(TypeOfValue value)
    {
        WriteLine("Value: {0}", value);
    }
}

This would produce:

Generic Values
----------------
Value: 246
Value: G
Value: 355.65
=================================
Press any key to close this window . . .

In the same way, you can use the parameter type in a constructor of the class. Here is an example:

public class Generator<T>
{
    public T Value;

    public Generator(T value)
    {
        
    }
}

Since the generic parameter and the parameter of the constructor are the same type, you can involve them in the same expression, such as assigning one to the other. Here is an example:

public class Generator<T>
{
    public T Value;

    public Generator(T value)
    {
        Value = value;
    }
}

Returning a Parameter Type

Besides, or as opposed to, passing a parameter type, in the class, you can create a method that returns a parameter type. Once again, you can primarily observe the rules we reviewed for returning a value from a function. Here is an example:

public class Generator<T>
{
    public T Value;

    public Generator(T value)
    {
        this.Value = value;
    }

    private T Create()
    {
        return this.Value;
    }
}

A Property of a Parameter Type

You can create a property that is of the parameter type of the generic class. There is no significant rule to follow when creating the property, except that you should remember that, at the time you are creating the property, the class "doesn't know" the type of the parameter. Here is an example:

public class Generator<T>
{
    public T val;

    public Generator(T value)
    {
        val = value;
    }

    public T Value
    {
        get { return val; }
        set { val = value; }
    }
}

Options on Generic Classes

A Generic Class with Multiple Type Parameters

As done for generic functions, when creating a generic class, you can specify more than one parameter type. To do this, in the <> operator, after the first generic type, enter a comma and another generic type. Here is an example:

public class Generator<OneType, AnotherType>
{
}

Once again, remember that, to make the parameter types simple to read, you can name them U, V, etc.

If you know for sure that the parameters will be of the same type, you can use one method to process both. Otherwise, you can declare the necessary members for each type. You can also create a method that would take many arguments with each argument of a particular type. Here are examples:

public class Generator<U, V>
{
    private U t;
    private V v;

    public void SetTValue(U value)
    {
        t = value;
    }

    public U GetTValue()
    {
        return t;
    }

    public void SetVValue(V value)
    {
        v = value;
    }
    public V GetVValue()
    {
        return v;
    }

    public string Show(U tValue, V vValue)
    {
        return $"{tValue}{vValue}";
    }
}

When declaring a variable for the class, make sure you appropriately specify the list of parameter types. Here are two examples:

using static System.Console;

Title = "Generic Vaplues";
WriteLine("Generic Values");
WriteLine("----------------");

Generator<int, int> yearlySalary = new Generator<int, int>();
yearlySalary.SetTValue(84);
yearlySalary.SetVValue(680);
string strNumber = yearlySalary.Show(yearlySalary.GetTValue(), yearlySalary.GetVValue());

WriteLine("Yearly Salary: {0}", strNumber);
            
Generator<char, double> price = new Generator<char, double>();
price.SetTValue('$');
price.SetVValue(185.45);
string strValues = price.Show(price.GetTValue(), price.GetVValue());

WriteLine(string.Format("Item Price: {0}", strValues));
            
Generator<short, decimal>  disparate = new Generator<short, decimal>();
disparate.SetTValue(425);
disparate.SetVValue(.35m);
strNumber = disparate.Show(disparate.GetTValue(), disparate.GetVValue());

WriteLine($"Some Number: {strNumber}");
            
Generator<int, string> company = new Generator<int, string>();
company.SetTValue(1800);
company.SetVValue("flowerslovers.com");
strNumber = company.Show(company.GetTValue(), company.GetVValue());

WriteLine($"Web Site: {strNumber}");

WriteLine("=================================");
            
namespace IntroductoryGenerics
{
    public class Generator<U, V>
    {
        private U t;
        private V v;

        public void SetTValue(U value)
        {
            t = value;
        }

        public U GetTValue()
        {
            return t;
        }

        public void SetVValue(V value)
        {
            v = value;
        }
        public V GetVValue()
        {
            return v;
        }

        public string Show(U tValue, V vValue)
        {
            return $"{tValue}{vValue}";
        }
    }
}

This would produce:

Generic Values
----------------
Yearly Salary: 84680
Item Price: $185.45
Some Number: 4250.35
Web Site: 1800flowers.com
=================================
Press any key to close this window . . .

You can also declare the variable using the var or the dynamic keyword. To do this, on the left side of the assignment operator, type only the var or the dynamic keyword and the name of the variable. Here is an example:

using static System.Console;

Title = "Generic Vaplues";
WriteLine("Generic Values");
WriteLine("--------------------------------");

Generator<int, int> yearlySalary = new Generator<int, int>();
yearlySalary.SetTValue(84);
yearlySalary.SetVValue(680);
string strNumber = yearlySalary.Show(yearlySalary.GetTValue(), yearlySalary.GetVValue());

WriteLine("Yearly Salary: {0}", strNumber);
            
Generator<char, double> price = new Generator<char, double>();
price.SetTValue('$');
price.SetVValue(185.45);
string strValues = price.Show(price.GetTValue(), price.GetVValue());

WriteLine(string.Format("Item Price: {0}", strValues));
            
var disparate = new Generator<short, decimal>();
disparate.SetTValue(425);
disparate.SetVValue(.35m);
strNumber = disparate.Show(disparate.GetTValue(), disparate.GetVValue());

WriteLine($"Some Number: {strNumber}");
            
dynamic company = new Generator<int, string>();
company.SetTValue(1800);
company.SetVValue("flowers.com");
strNumber = company.Show(company.GetTValue(), company.GetVValue());

WriteLine($"Web Site: {strNumber}");

WriteLine("=================================");
            
namespace IntroductoryGenerics
{
    public class Generator<U, V>
    {
        private U t;
        private V v;

        public void SetTValue(U value) => t = value;
        public U GetTValue() => t;
        public void SetVValue(V value) => v = value;
        public V GetVValue() => v;
        public string Show(U tValue, V vValue) => $"{tValue}{vValue}";
    }
}

If a generic class has more than one parameter type, they don't have to be of the same type. At the time you are creating the class, you may not specify their types but you can anticipate that they would be different. It is when you declare the variable that you would need to determine their types.

Even if the parameters are of primitive types, you can first declare the variables and pass them to the class.

A Class as a Parameter Type

So far, in our examples, we treated the parameter type as a primitive data type. A parameter type can also be a formal class, either a class that you created yourself or one that exists in any available library, including the .NET Framework. When creating the generic class, you must follow all the rules we have reviewed so far for generic classes. Here is such a simple class:

public class Generator<T>
{
    public string Show(T val)
    {
        return $"{val}";
    }
}

As mentioned already, the class that would be processed by the generic class must have been previously created so it can be used as a parameter. Here is an example:

public class FourSideGeometricFigure
{
    public string? Name  { get; set; }
    public double Base   { get; set; }
    public double Height { get; set; }
    
    public double Area
    {
        get { return Base * Height; }
    }

    public override string ToString()
    {
        return $"Type:  {Name}, Base: {Base}, Height: {Height}, Area: {Area}";
    }
}

public class Generator<T>
{
    public string Show(T val)
    {
        return val!.ToString()!;
    }
}

When declaring a variable of the generic class, make sure you enter the name of the normal class in place of the parameter type. You can declare the variable using its name or using the var or the dynamic keyword. Here are examples:

using static System.Console;

Title = "Generic Vaplues";
WriteLine("Generic Values");
WriteLine("--------------------------------");

FourSideGeometricFigure sqr = new FourSideGeometricFigure();
sqr.Name = "Square";
sqr.Base = 36.82;
sqr.Height = 36.82;
Generator<FourSideGeometricFigure> exoSquare =
                    new Generator<FourSideGeometricFigure>();

WriteLine("Shape Summary\n\t{0}", exoSquare.Show(sqr));
WriteLine("--------------------------------");

var rect = new FourSideGeometricFigure();
rect.Name = "Rectangle";
rect.Base = 52.94;
rect.Height = 27.58;

dynamic exoRect = new Generator<FourSideGeometricFigure>();

WriteLine(string.Format("Shape Summary\n\t{0}", exoRect.Show(rect)));

WriteLine("=================================");

namespace IntroductoryGenerics
{
    public class FourSideGeometricFigure
    {
        public string? Name  { get; set; }
        public double Base   { get; set; }
        public double Height { get; set; }
        
        public double Area
        {
            get { return Base * Height; }
        }

        public override string ToString()
        {
            return $"Type:  {Name}\n\tBase: {Base}\n\tHeight: {Height}\n\tArea: {Area}";
        }
    }

    public class Generator<T>
    {
        public string Show(T val)
        {
            return val.ToString();
        }
    }
}

This would produce:

Generic Values
--------------------------------
Shape Summary
        Type:  Square
        Base: 36.82
        Height: 36.82
        Area: 1355.7124
--------------------------------
Shape Summary
        Type:  Rectangle
        Base: 52.94
        Height: 27.58
        Area: 1460.0852
=================================
Press any key to close this window . . .

Previous Copyright © 2008-2025, FunctionX Saturday 19 March 2022 Next