Home > Back-end >  How to pass Type as a Parameter to Method
How to pass Type as a Parameter to Method

Time:12-28

Im new to C# however im running into an issue when trying to pass the TableOne type class into a method and use within the method itself.

Class:

    public class TableOne
    {
        public List<string> CaseID { get; set; }
        public List<string> Owner { get; set; }
        public List<string> Assignee { get; set; }
        public List<string> Comments { get; set; }
    }

Method:

public static string ComposeHtmlTable<T>(Type classType, IList<T> table)
{
    List<classType> test = table.Cast<classType>().ToList();
    Console.WriteLine(test[0].CaseID[0]); // trying to access data

    return "test";
}

How the method is being called:

ComposeHtmlTable<TableOne>(typeof(TableOne), data.TableOne);

Error im receiving:

'classType' is a variable but is used like a type.

The reason why its imperative that the method uses the parameter type is because there might be multiple types i.e. TableTwo or TableThree that I might pass into that method.

Any ideas on how I can tackle this?

TIA

CodePudding user response:

The problem is in this line of code List<classType> test = table.Cast<classType>().ToList(); List<classType> and Cast<classType> is invalid syntax. List<T> is acceptable.

Type arguments in c# are sent separately to variables. You've already supplied the type argument T to the generic method. So use List<T> and Cast<T> instead.

Hence passing in classType as a variable is redundant.
Even if you needed to do a switch expression on the the type of elements supplied you can switch on typeof(T)

CodePudding user response:

As @Dai suggest, you could replace the classType parameter by an generic type parameter:

static List<T1> ComposeHtmlTable<T1,T2>(IList<T2> table)
{        
    List<T1> test = table.Cast<T1>().ToList();
    return test;
}

PS: I changed your method to return the new List, since I presume that's what you wanted to achieve...

And call it like:

ComposeHtmlTable<TableOne,TableOne>(data.TableOne);

If the two generic types will always be the same you can rteduce the method to:

static List<T> ComposeHtmlTable<T>(IList<T> table)
{
    return (List<T>) table.Cast<T>().ToList();
}

and call it like:

ComposeHtmlTable<TableOne>(data.TableOne);

CodePudding user response:

Let's have a look at classType and T:

public static string ComposeHtmlTable<T>(Type classType, IList<T> table)
{
    List<classType> test = table.Cast<classType>().ToList();
    Console.WriteLine(test[0].CaseID[0]); // trying to access data

    return "test";
}

Can they be some arbitrary types, say T == int and classType == StringBuider? Definitely not. As I can see, both classType and T should be inherited from TableOne. Let's .net know it:

public static string ComposeHtmlTable<C, T>(IList<T> table) 
  where C : TableOne
  where T : TableOne 
{...}
      

Time to add some details:

  • we don't want IList<T> table as an argument, IEnumerable<T> table is enough (and we will be able to pass not only lists, by, say, arrays)
  • the method is declares as public, any input is possible; so we have to validate input arguments
  • what if test is empty (i.e. it doesn't have any items?). We can't obtain test[0].CaseID[0] in this case.
public static string ComposeHtmlTable<C, T>(IEnumerable<T> table) 
  where C : TableOne
  where T : TableOne 
{
    if (table is null)
        throw new ArgumentNullException(nameof(table));  

    List<C> test = table.Cast<C>().ToList();

    if (test.Count > 0 && test[0] != null && test[0].CaseID.Count > 0)
        Console.WriteLine(test[0].CaseID[0]); // trying to access data  
    else
        Console.WriteLine("test is empty");

   return "test"; 
}
  •  Tags:  
  • c#
  • Related