简体   繁体   中英

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM