Conditional typing in generic method

c#, generics, variance

Solution

If you're making these types of checks in a generic method, I'd rethink your design. The method is obviously not truly generic - if it were, you wouldn't need specific type checking...

Situations like this typically can be handled more cleanly by a redesign. One alternative is often to provide an overload of the appropriate type. Other design alternatives which avoid the type-specific behavior exist, as well, such as Richard Berg's suggestion of passing in a delegate.

Problem

Consider the following (heavily simplified) code: ``` public T Function<T>() { if (typeof(T) == typeof(string)) { return (T) (object) "hello"; } ... } ``` It's kind of absurd to first cast to `object`, then to `T`. But the compiler has no way of knowing that the previous test assured `T` is of type `string`. What is the most elegant, idiomatic way of achieving this behavior in C# (which includes getting rid of the stupid `typeof(T) == typeof(string)`, since `T is string` can't be used)? Addendum: There is no return type variance in .net, so you can't make a function overload to type string (which, by the way, is just an example, but one reason why association end redefinition in polymorphism, e.g. UML, can't be done in c#). Obviously, the following would be great, but it doesn't work: ``` public T Function<T>() { ... } public string Function<string>() { return "hello"; } ``` Concrete Example 1: Because there's been several attacks to the fact that a generic function that tests for specific types isn't generic, I'll try to provide a more complete example. Consider the Type-Square design pattern. Here follows a snippet: ``` public class Entity { Dictionary<PropertyType, object> properties; public T GetTypedProperty<T>(PropertyType p) { var val = properties[p]; if (typeof(T) == typeof(string) { (T) (object) p.ToString(this); // magic going here } return (T) TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(val); } } ``` Concrete Example 2: Consider the Interpreter design pattern: ``` public class Expression { public virtual object Execute() { } } public class StringExpression: Expression { public override string Execute() { } // Error! Type variance not allowed... } ``` Now let's use generics in Execute to allow the caller to force a return type: ``` public class Expression { public virtual T Execute<T>() { if(typeof(T) == typeof(string)) { // what happens when I want a string result from a non-string expression? return (T) (object) do_some_magic_and_return_a_string(); } else if(typeof(T) == typeof(bool)) { // what about bools? any number != 0 should be True. Non-empty lists should be True. Not null should be True return (T) (object) do_some_magic_and_return_a_bool(); } } } public class StringExpression: Expressiong { public override T Execute<T>() where T: string { return (T) string_result; } } ```

Original source