Share via


C# How to return instance dynamically by generic

Question

Friday, October 28, 2016 2:16 PM

see my code

class Program
{
    static void Main(string[] args)
    {
        Employee T = GetInstance<Importance.Employee>(Importance.Employee);
    }

    public static T GetInstance<T>(Importance objType)
    {
        if (objType == Importance.Employee)
            return (T)Convert.ChangeType((new Employee()), typeof(T));
        else 
            return (T)Convert.ChangeType((new Teacher()), typeof(T));
    }
}

public class Employee
{
    string ID = "";
    string Name = "";
}

public class Teacher
{
    string ID = "";
    string Name = "";
}

enum Importance
{
    Employee,
    Teacher
};

this line is not working Employee emp = GetInstance<Importance.Employee>(Importance.Employee); throwing error 'GenericFunction.Importance.Employee' is a 'field' but is used like a 'type'

where i made the mistake. please help because i am trying to learning generic because i weak there. thanks

All replies (6)

Friday, October 28, 2016 2:32 PM ✅Answered | 1 vote

As explained in my previous post, the generic parameter is a type.

You are getting confused with types and normal parameters and seem to be trying to mix up two classes.

If you have a method defined as:

public static T GetInstance<T>(Importance objType)

Then T must be a type such as string or int or Employee etc.

objType is an argument of type Importance and has nothing to do with T.

The return type of the method is defined as being of type T (so if you used <Employee> as the generic type, then the method will return an instance of the Employee class.

So..the expected usage would be:

Employee employee = GetInstance<Employee>(Importance.Employee);

Note that T is the Employee type. NOT AN ENUM.

I can't say whether your type conversion code in the method itself will work either...in fact, the whole generic approach doesn't really seem appropriate here. Have you considered an interface?

public interface IPerson
{
   public string ID {get;set}
   public string Name {get;set;}
}

public class Employee: IPerson
{
  public string ID {get;set;}
  public string Name {get; set;}
}

public class Teacher: IPerson
{
  public string ID {get;set;}
  public string Name {get; set;}
}

////... then..your method to return an instance

public static IPerson GetInstance(Importance imp)
{
   if (imp = Importance.Employee)
   {
      return new Employee();
   }
   else
   {
      return new Teacher();
   }
}

Sunday, October 30, 2016 8:21 PM ✅Answered

The generic GetInstance method returns an instance of type T. You must define this type T when you call the method at compile time.

So if you want the method to return an Empoyee you must specify the type argument as Employee and nothing else:

Employee objInstance = GetInstance<Employee>(Importance.Employee);

The type T bascally gets replated with the type that you specify as the type argument when you compile the application. So your method will actually be compiled into something like this:

        public static Employee GetInstance(Importance objType)
        {
            if (objType == Importance.Employee)
                return (Employee)Convert.ChangeType((new Employee()), typeof(T));
            else
                return (Employee)Convert.ChangeType((new Teacher()), typeof(T));
        }

...which means that you will (always) get a runtime error if you pass in any value other than Importance.Employee at runtime since a Teacher object cannot be converted to an Employee object.

So if you want the GetInstance method to be able to return either an employee or a teacher based on the Importance value that you pass to the method dynamically at runtime, using generics is not the way to go. Instead the method should just return a common base type for both the Employee and Teacher types as suggested by RJP1973 above:

    public abstract class Person
    {
        string ID { get; set; }
        string Name { get; set; }
    }

    public class Employee : Person
    {
    }

    public class Teacher : Person
    {
    }
class Program
    {
        static void Main(string[] args)
        {
            Employee objInstance = GetInstance(Importance.Employee) as Employee;
        }

        public static Person GetInstance(Importance objType)
        {
            if (objType == Importance.Employee)
                return new Employee();
            else
                return new Teacher();
        }
    }

Hope that helps.

Please remember to close your threads by marking helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.


Monday, October 31, 2016 9:41 AM ✅Answered

1st Approach

class Program
{
    static void Main(string[] args)
    {
        Employee employee = GetInstance<Employee>(Importance.Employee);
        Teacher teacher = GetInstance<Teacher>(Importance.Teacher);

        Console.WriteLine(employee.GetType());
        Console.WriteLine(teacher.GetType());

        Console.ReadKey();
    }

    public static T GetInstance<T>(Importance objType)
    {
        if (objType == Importance.Employee)
            return (T)Convert.ChangeType((new Employee()), typeof(T));
        else
            return (T)Convert.ChangeType((new Teacher()), typeof(T));
    }
}

public class Employee
{
    string ID = "";
    string Name = "";
}

public class Teacher
{
    string ID = "";
    string Name = "";
}

enum Importance
{
    Employee,
    Teacher
};

2nd approach.don't need the Importance enum here if i want a new object of the given type. we can do something like:

class Program
{
    static void Main(string[] args)
    {
        Employee employee = GetInstance<Employee>();
        Teacher teacher = GetInstance<Teacher>();

        Console.WriteLine(employee.GetType());
        Console.WriteLine(teacher.GetType());

        Console.ReadKey();
    }

    public static T GetInstance<T>() where T : class, new()
    {
        return new T();
    }
}

public class Employee
{
    string ID = "";
    string Name = "";
}

public class Teacher
{
    string ID = "";
    string Name = "";
}

3rd approach

We can think a little bit more and give two samples. One with Enum, and one with Polimorphism.

If we really want to keep with the Enum, then I think your generic type with the Enum argument serves only to ensure that it will not return a different type, so it would be something like:

class Program
{
    static void Main(string[] args)
    {
        var employee = GetInstance<Employee>(Importance.Employee);
        var teacher = GetInstance<Teacher>(Importance.Teacher);

        Console.WriteLine(employee.GetType());
        Console.WriteLine(teacher.GetType());

        Console.ReadKey();
    }

    public static T GetInstance<T>(Importance importance) where T : Role, new()
    {
        if (typeof(T) == typeof(Employee) && importance != Importance.Employee)
        {
            throw new InvalidCastException();
        }

        if (typeof(T) == typeof(Teacher) && importance != Importance.Teacher)
        {
            throw new InvalidCastException();
        }

        return new T();
    }
}

public abstract class Role { }

public class Employee : Role
{
    string ID = "";
    string Name = "";
}

public class Teacher : Role
{
    string ID = "";
    string Name = "";
}

public enum Importance
{
    Teacher,
    Employee
}

4th approach. I would do something like:

class Program
{
    static void Main(string[] args)
    {
        var employee = GetInstance<Employee>();
        var teacher = GetInstance<Teacher>();

        Console.WriteLine(employee.GetType());
        Console.WriteLine(teacher.GetType());

        Console.ReadKey();
    }

    public static T GetInstance<T>() where T : Role, new()
    {
        var role = new T();
        // do something important here

        return role;
    }
}

public abstract class Role { }

public class Employee : Role
{
    string ID = "";
    string Name = "";
}

public class Teacher : Role
{
    string ID = "";
    string Name = "";
}


Friday, October 28, 2016 7:46 PM

This should work too:

    Employee T = new Employee();

or:

    Employee T = GetInstance<Employee>();
    . . .
    public static T GetInstance<T>() where T : new()

    {

        return new T();

    }


Saturday, October 29, 2016 3:54 PM

i want to call GetInstance like below way. so please tell me how to write GetInstance function with generic type with T.

IPerson objInstance = GetInstance<Employee>(Importance.Employee);

thanks


Saturday, October 29, 2016 3:55 PM

please give me full code for GetInstance which return instance dynamically. see my code and from there code intention will be clear what i am trying to do. so post code which guide me how to achieve what i am trying to do with generic T thanks