T B H P N

C# Generics

Synopsis:

A C# Generic is a class that depends on one or more parameters that are not specified until an application uses it. Unlike C++ templates, C# generics are created at run time1, and so, do not support specialization. You can, however, define a constraint that supports using features of specific generic types.
Here is a demonstration Generic class that has a very typical structure, including a public string property, a property of the generic type, and method for display.

Code in File GenericsDemo.cs

  /////////////////////////////////////////////////////////////////////
  // GenericsDemo.cs - demonstrate basic generic class structure     //
  //                                                                 //
  // Jim Fawcett, CSE681 - Software Modeling and Analysis, Fall 2017 //
  /////////////////////////////////////////////////////////////////////

  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;

  namespace Generics
  {
    public class X<T>
    {
      public string name { get; set; } = "T container";
      public T value { get; set; }
      public void say()
      {
        Console.Write(
          "\n  my name is {0}\n  I hold an instance of {1} with value {2}",
          name, typeof(T).Name, value.ToString()
        );
      }
    }

    class TestX
    {
      static void Main(string[] args)
      {
        Console.Write("\n  Demonstrate Simple Generic Class");
        Console.Write("\n ==================================");

        Y y = new Y();
        X<int> x1 = new X<int>();
        x1.name = "x1";
        x1.value = 3;
        x1.say();
        X<double> x2 = new X<double>();
        x2.name = "x2";
        x2.value = 3.1415927;
        x2.say();
        X<string> x3 = new X<string>();
        x3.name = "x3";
        x3.value = "aeiou";
        x3.say();
        Console.Write("\n\n");
      }
    }
  }

Output

  Demonstrate Simple Generic Class
 ==================================
  my name is x1
  I hold an instance of Int32 with value 3
  my name is x2
  I hold an instance of Double with value 3.1415927
  my name is x3
  I hold an instance of String with value aeiou

Press any key to continue . . .

The code below extends the previous demonstration by adding another generic parameter, which requires a constraint. The second parameter is used to declare a reference member which needs a default constructor. To compile, the code needs a constraint promising that the type, U, has a default constructor.

Code in File GenericsDemoEx.cs

  /////////////////////////////////////////////////////////////////////
  // GenericsDemoEx.cs - demonstrate basic generic class structure   //
  // - extended, two generic parameters, one with constraint         //
  // Jim Fawcett, CSE681 - Software Modeling and Analysis, Fall 2017 //
  /////////////////////////////////////////////////////////////////////

  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;

  namespace Generics
  {
    public class X<T, U> where U : new()                   // constraint
    {
      public string name { get; set; } = "T container";
      public T value { get; set; }
      public void setU(U u)
      {
        u_ = u;
      }
      public void say()
      {
        Console.Write(
          "\n  my name is {0}\n  I hold an instance of {1} with value {2}",
          name, typeof(T).Name, value.ToString()
        );
        if (u_ == null)
          return;
        Console.Write(
          "\n  I also hold an instance of {0} with value {1}",
          typeof(U).Name, u_.ToString()
        );
      }
      private U u_;                                        // private member requiring default construction
    }

    public class Y
    {
      public override string ToString() { return "Y()"; }
    }

    class TestX
    {
      static void Main(string[] args)
      {
        Console.Write("\n  Demonstrate Simple Generic Class");
        Console.Write("\n ==================================");

        Y y = new Y();
        X<int,Y> x1 = new X<int,Y>();
        x1.name = "x1";
        x1.value = 3;
        x1.setU(y);
        x1.say();
        X<double,Y> x2 = new X<double,Y>();
        x2.name = "x2";
        x2.value = 3.1415927;
        x2.say();
        X<string,Y> x3 = new X<string,Y>();
        x3.name = "x3";
        x3.value = "aeiou";
        x3.say();
        Console.Write("\n\n");
      }
    }
  }

Output:

  Demonstrate Simple Generic Class
 ==================================
  my name is x1
  I hold an instance of Int32 with value 3
  I also hold an instance of Y with value Y()
  my name is x2
  I hold an instance of Double with value 3.1415927
  my name is x3
  I hold an instance of String with value aeiou

Press any key to continue . . .

Example Code:


  1. Generics are created at run-time

CST strip