fat_flying_pigs
fat_flying_pigs

Reputation: 90

c# Prioritizing extension methods (only)

Let me start with the code... Please note this is not a question about overriding instance methods - this deals purely with extension methods. This code is being used in the Unity3D game engine, version 5.3.x

public static class ExtentionMethods {

    public static string ToJson<T>(this List<T> list) {
        string s = "[";
        for (int i = 0; i < list.Count; i++) {
            if (i > 0)
                s += ",";
            s += list[i].ToJson();
        }
        return s + "]";
    }

    public static string ToJson(this object o) {
        if (o == null)
            return "null";
        return o.ToString();
    }

    public static string ToJson(this string value){
        return "\"" + value + "\"";
    }
}

and

public List<string> list = new List<string>();
void Start () {
    list.Add ("dog0");
    list.Add ("dog1");
    list.Add ("dog2");
    Debug.Log (list.ToJson());  

    string s = "elephants";
    Debug.Log (s.ToJson());  
}

The output is as follows:

[dog0,dog1,dog2]
"elephants"

It seems that a string calling the ToJson() function may use either the object or the string type. Is there any way to make it only use the string version of the method?

Upvotes: 2

Views: 102

Answers (3)

Mustafa Ekici
Mustafa Ekici

Reputation: 7470

You have to check what type of T is:

s += typeof(T)==typeof(string) ? list[i].ToString().ToJson() : list[i].ToJson();

Upvotes: 1

Ramazan Binarbasi
Ramazan Binarbasi

Reputation: 787

There's no way without checking type and calling matching type's ToJson method with a cast. (Petter already gave an answer about this)

If I was facing similar problem, I would add another extension for string lists:

public static string ToJson(this List<string> list) {
   // ... Body is the same with other ToJson<T>(List<T>)
}

This way string lists get bind to this method during compile. Since compiler knows that values are string, inner ToJson method will be bind correctly with string one.

Upvotes: 1

Petter Hesselberg
Petter Hesselberg

Reputation: 5498

At this point:

s += list[i].ToJson();

...all the compiler knows is that list[i] is an object, so that's the extension method you get. You'd have to look at the type of list[i] and call the string overload if it's a string, e.g.,

object o = list[i];
string s = o as string;
if (s != null)
{
    s += s.ToJson();
}
else
{
    s += o.ToJson();
}

Extension methods are nice syntactic sugar, but don't expect too much in the way of generic magic. :-)

Upvotes: 2

Related Questions