LCaraway
LCaraway

Reputation: 1357

C# Generics - Return a List with a Type Dependent of Parameter.

Full disclosure, I do not fully understand generics but am hoping the answer to this question will clear things up.

I have an application that allows a user to build a query of their own. The query will leverage the Entity Framework. I would like to return a list of the results whose type is dependent upon what column they queried. In other words i need a method that could have multiple return types. I derive the type using reflection on the column and then would like to pass to this method.

    public static T getValues<T>(string ColName, Type type)
    {
        var result = db.AC_PROPERTY.Select(ColName);

        if (type == typeof(string))
        {
            List<string> list = new List<string>();
            //Query and add results to list. 
            return list;

        }

        if (type == typeof(double?) || type == typeof(double))
        {
            List<double> list = new List<double>();
            //Query and add results to list. 
            return list;

        }

        if (type == typeof(int) || type == typeof(int?))
        {
            List<int> list = new List<int>();
            //Query and add results to list. 
            return list;
        }

        if (type == typeof(DateTime))
        {
            List<DateTime> list = new List<DateTime>();
            //Query and add results to list. 
            return list;

        }
    }

I am getting an error stating that I cannot implicitly convert List (or the respective type) to T.

Can someone explain this and perhaps walk me through how to accomplish this.

Upvotes: 1

Views: 573

Answers (1)

Flater
Flater

Reputation: 13783

Ask yourself this: How are T and Type type meaningfully different? Why do you need both?

You don't.

Furthermore, while it's technically possible to check for a generic parameter's type, you should not be doing this. It's a code smell. If your method is generic, the method body should be generic as well. This includes not needing to know the exact value of T.

1. Get rid of Type type

public static List<T> getValues<T>(string ColName)
{
    //...
}

Notice how this method would be used:

List<DateTime> myDateList = getValues<DateTime>("MyDateTimeColumn");

2. Make the method body generic

public static List<T> getValues<T>(string ColName)
{
    List<T> myReturnList = new List<T>();
    var selectedColumnValues = db.AC_PROPERTY.Select(ColName);

    //Query and add results to list. 

    return myReturnList;
}

Looks a lot neater, doesn't it? I noticed you omitted the actual creating of the list; so I omitted it too for now.


I could get into the rest of the method body based on some assumptions, but there's a much more relevant consideration here.

Your method seems to be no different from LINQ's Select() method!

So instead of doing this with your custom built getValues<T> method:

List<DateTime> myDateList = getValues<DateTime>("MyDateTimeColumn");

You can use the existing LINQ method:

List<DateTime> myDateList = myDataList.Select(item => item.MyDateTimeProperty).ToList();

(Note: ToList() can be optional but is advisable due to lazy evaluation).

Upvotes: 5

Related Questions