c#优先考虑扩展方法(仅限)

时间:2016-01-26 00:06:56

标签: c#

让我从代码开始...请注意这不是关于覆盖实例方法的问题 - 这完全涉及扩展方法。此代码用于Unity3D游戏引擎版本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 + "\"";
    }
}

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());  
}

输出如下:

[dog0,dog1,dog2]
"elephants"

调用ToJson()函数的字符串似乎可以使用对象或字符串类型。有没有办法让它只使用方法的字符串版本?

3 个答案:

答案 0 :(得分:2)

此时:

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

...所有编译器都知道list[i]是一个对象,所以你得到的是扩展方法。您必须查看list[i]的类型,如果它是一个字符串,则调用字符串重载,例如,

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

扩展方法是一种很好的语法糖,但是对于通用魔法的方式并不过分。 : - )

答案 1 :(得分:1)

没有检查类型并且使用强制转换调用匹配类型的ToJson方法是没有办法的。 (彼得已经给出了答案)

如果我遇到类似的问题,我会为字符串列表添加另一个扩展名:

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

这样,字符串列表在编译期间就会绑定到此方法。由于编译器知道值是字符串,因此内部ToJson方法将与字符串1正确绑定。

答案 2 :(得分:1)

您必须检查T的类型:

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