Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the advantages of using generics in method signatures?

Tags:

c#

generics

(Thanks everyone for the answers, here is my refactored example, in turn another StackOverflow question about the Single Responsibility Principle.)

Coming from PHP to C#, this syntax was intimidating:

container.RegisterType<Customer>("customer1");

until I realized it expresses the same thing as:

container.RegisterType(typeof(Customer), "customer1");

as I demonstrate in the code below.

So is there some reason why generics is used here (e.g. throughout Unity and most C# IoC containers) other than it just being a cleaner syntax, i.e. you don't need the typeof() when sending the type?

using System;

namespace TestGenericParameter
{
    class Program
    {
        static void Main(string[] args)
        {
            Container container = new Container();
            container.RegisterType<Customer>("test");
            container.RegisterType(typeof(Customer), "test");

            Console.ReadLine();
        }
    }

    public class Container
    {
        public void RegisterType<T>(string dummy)
        {
            Console.WriteLine("Type={0}, dummy={1}, name of class={2}", typeof(T), dummy, typeof(T).Name);
        }

        public void RegisterType(Type T, string dummy)
        {
            Console.WriteLine("Type={0}, dummy={1}, name of class={2}", T, dummy, T.Name);
        }

    }

    public class Customer {}
}

//OUTPUT:
//Type=TestGenericParameter.Customer, dummy=test, name of class=Customer
//Type=TestGenericParameter.Customer, dummy=test, name of class=Customer
like image 764
Edward Tanguay Avatar asked Nov 28 '22 05:11

Edward Tanguay


2 Answers

One reason when generics are very useful is when the generic type parameter is used as the type of a parameter or as the return type of the method. That means, you can write methods like

public T GetAs<T>(string name)

where the return type can be checked by the compiler and boxing value types can sometimes be avoided. The caller would write:

int value = GetAs<int>("foo");

Whithout generics, you would have to write

public object GetAs(Type t, string name)

and the caller has to cast the result again:

int value = (int)GetAs(typeof(int), "foo");
like image 53
EFrank Avatar answered Nov 30 '22 18:11

EFrank


A primary reason is the type safety at compile time. If you are passing two Type objects you are placing the responsibility at the developer instead of the compiler.

This is also why many IoC containers utilizes it, as your compiler will complain if an concrete type isn't inheriting the abstract type.

public void Register<TAbstract, TConcrete>() where TConcrete : TAbstract
{
}

This code will only work if TConcrete is implementing or inheriting TAbstract. If this method took two Type parameters, your method should validate this relationship.

like image 28
Troels Thomsen Avatar answered Nov 30 '22 18:11

Troels Thomsen