Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# typeof applied to generic parameter supertype

I have a method, it doesn't have any T parameters.

Unfortunately, C# typeof operator doesnt work on generics as shown bellow.

public static string ToString(object obj)
{
    if (obj.GetType() == typeof(List<object>))
    {
        return "Bug: Never called";
    }
    if (obj.GetType() == typeof(List<int>))
    {
        return "Method only works for int lists";
    }
    return "";
}

Expected output: ToString(List of ints) would return "Bug: Never Called".

Actual output: "Method only works for int lists"

This worked perfectly fine in Java. You will say that generics in c# don't support this. How can I restructure my code to make "ToString(object)" method work for a list of objects?

Requirements : You cannot modify the method's signature, only its implementation.

Unfortunately you cannot make "int" class implement an interface. Since int class was written by Microsoft. As such I cannot add a visitor pattern on int type.

like image 427
user2186597 Avatar asked Feb 06 '23 13:02

user2186597


1 Answers

Unfortunately, c# typeof operator doesn't work on generics as shown bellow.

Actually, it's quite fortunate that it doesn't work as you expect it to work. Unlike Java, C# differentiates between List<int> and List<object> at runtime, not only at compile time. Type information for generics instantiated with primitive type parameters lets .NET produce more efficient code by avoiding type erasure.

If you would like to test if an object is any generic list, use this check instead:

var objT = obj.GetType();
if (objT.IsGenericType && objT.GetGenericTypeDefinition() == typeof(List<>)) {
    ...
}

As such I cannot add a visitor pattern on int type.

C# gives you a powerful mechanism for dispatching dynamically without implementing an interface. For example, you can do this:

public static string ToString(object obj) {
    var list = obj as IList;
    if (list != null) {
        foreach (dynamic o in list) {
            Process(o);
        }
    }
}
static void Process(int n) { ... }
static void Process(string s) { ... }
static void Process(object o) { ... }

The above will choose the right implementation of Process based on the run-time type of the object in your list.

like image 56
Sergey Kalinichenko Avatar answered Feb 15 '23 01:02

Sergey Kalinichenko