-1

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

Gilad Green
  • 36,708
  • 7
  • 61
  • 95
Mou
  • 15,673
  • 43
  • 156
  • 275
  • While the cause of the error message is clear, what is not clear at all is what you're actually trying to do. Both answers posted so far provide useful advice, but there's nothing in your question that explains why you are using such convoluted code to do what effectively boils down to just writing `Employee T = new Employee();`. I.e. why have the `GetInstance()` method at all if the caller is required to know the type being returned? Please improve your question so that there's a comprehensible reason for the code you're trying to get to work. See [ask] for advice on how to do that. – Peter Duniho Oct 28 '16 at 18:24
  • 1
    In the meantime, you _might_ find these questions useful: https://stackoverflow.com/questions/10921300/generic-methods-returning-simple-types, https://stackoverflow.com/questions/5871702/trouble-with-type-casting-in-c-sharp, https://stackoverflow.com/questions/12625209/returning-generic-without-knowing-type, and https://stackoverflow.com/questions/3824484/create-object-of-parameter-type, to name a few possibly related questions. – Peter Duniho Oct 28 '16 at 18:25

2 Answers2

1

When using it like this you are actually addressing your enum of Importance with the value of Employee - which is not a type, but a value.

Instead of defining method this way add a base class of Role:

public class Role
{
    public string Id { get; set; }
    public string Name { get; set; }
}

public class Employee : Role
{
}

public class Teacher : Role
{
}

And the method:

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

This is basically the Factory design pattern


In your scenario it makes no sense to have the method generic and then pass the enum value to determine what type to instantiate. Moreover in your current implementation if you pass T as Teacher and the Importance.Employee value:

var obj = Convert.ChangeType((new Employee()), typeof(Teacher));

you will get:

InvalidCastException - Object must implement IConvertible

Decide what you want to do. If you want a mapping value like the enum (and example above) or a generic function that gets the T type to instantiate:

public static TRole GetInstance<TRole>() where TRole : Role, new()
{
    return new TRole();
}

Employee T = GetInstance<Employee>();
Gilad Green
  • 36,708
  • 7
  • 61
  • 95
  • i am return type and parameter of GetInstance function should be T. also show me how call GetInstance function when return type and parameter of GetInstance function is T. post another version of code if possible. thanks – Mou Oct 28 '16 at 14:25
1

As Gilad Green said, you are using a value as a type. You can do something like:

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
};

But, as I see, you don't need the Importance enum here if you just want a new object of the given type. You 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 = "";
}

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

If you 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
}

But I don't think it makes sense. 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 = "";
}
Community
  • 1
  • 1
Rafael Marques
  • 1,501
  • 15
  • 23