views:

744

answers:

7

I have a method that uses an IList as a parameter. I need to check what the type of that T object is and do something based on it. I was trying to use the T value, but the compiler does not not allow it. My solution is the following:

private static string BuildClause<T>(IList<T> clause)
{
    if (clause.Count > 0)
    {
        if (clause[0] is int || clause[0] is decimal)
        {
           //do something
        }
        else if (clause[0] is String)
        {
           //do something else
        }
        else if (...) //etc for all the types
        else
        {
           throw new ApplicationException("Invalid type");
        }
    } 
}

There has to be a better way to do this. Is there some way I can check the type of T that is passed in and then use a switch statement?

+2  A: 

The typeof operator...

typeof(T)

... won't work with the c# switch statement. But how about this? The following post contains a static class...

http://stackoverflow.com/questions/298976/c-is-there-a-better-alternative-than-this-to-switch-on-type

...that will let you write code like this:

TypeSwitch.Do(
    sender,
    TypeSwitch.Case<Button>(() => textBox1.Text = "Hit a Button"),
    TypeSwitch.Case<CheckBox>(x => textBox1.Text = "Checkbox is " + x.Checked),
    TypeSwitch.Default(() => textBox1.Text = "Not sure what is hovered over"));
Robert Harvey
Also see JaredPar's answer here.
Robert Harvey
+6  A: 

You could use overloads:

public static string BuildClause(List<string> l){...}

public static string BuildClause(List<int> l){...}

public static string BuildClause<T>(List<T> l){...}

Or you could inspect the type of the generic parameter:

Type listType = typeof(T);
if(listType == typeof(int)){...}
jonnii
+1: overloads are definitely the *best* solution here in terms of design and long-term maintainability. A runtime type-check of a generic parameter just seems too ironic to code with a straight face.
Juliet
+2  A: 

You can use typeof(T).

private static string BuildClause<T>(IList<T> clause)
{
     Type itemType = typeof(T);
     if(itemType == typeof(int) || itemType == typeof(decimal))
    ...
}
bdowden
+1  A: 

You can do typeOf(T), but I would double check your method and make sure your not violating single responsability here. This would be a code smell, and thats not to say it shouldn't be done but that you should be cautios.

The point of generics is being able to build type agnostic algorthims were you don't care what the type is or as long as it fits within a certain set of criteria. Your implementation isn't very generic.

JoshBerke
+1  A: 

There is no way to use the switch statement for what you want it to do. The switch statement must be supplied with integral types, which does not include complex types such as a "Type" object, or any other object type for that matter.

womp
+2  A: 

Your construction completely defeats the purpose of a generic method. It's ugly on purpose because there must be a better way to achieve what you're trying to accomplish, although you haven't given us quite enough information to figure out what that is.

mquander
+1  A: 

By default know there is not a great way. Awhile back I got frustrated with this and wrote a little utility class that helped out a bit and made the syntax a bit cleaner. Essentially it turns the code into

TypeSwitcher.Do(clause[0],
  TypeSwitch.Case<int>(x => ...),  // x is an int
  TypeSwitch.Case<decimal>(d => ...), // d is a decimal 
  TypeSwitch.Case<string>(s => ...)); // s is a string

Full blog post and details on the implementation are available here

JaredPar