2012-02-10 47 views
3

为什么会发生这种情况?请注意下面的代码:使用扩展方法时发生意外的行为

static class StringExtension 
{ 
    public static string Remove(this string s, char c) 
    { 
     return s.Replace(c.ToString(), ""); 
    } 
    public static string Remove(this string s, char[] a) 
    { 
     foreach (char c in a) 
     { 
      s = s.Remove((char)c); // <---- ArgumentOutOfRange Exception here 
     } 
     return s; 
    } 
} 
class Program 
{ 

    static void Main(string[] args) 
    { 
     char[] a = new char[] { '.', ',' }; 

     string testString = "Clean.this,string.from,periods.and,commas."; 

     Console.WriteLine(testString.Remove(a)); 

    } 
} 

当我运行这段代码,我得到一个ArgumentOutOfRange异常的指示线。原来,即使我有一个扩展的特定代码Remove(this,char),我明确地(虽然,应该没有理由)指定参数的类型,它忽略我的扩展并尝试调用原始的Remove( int)方法。

我做错了什么或这是C#中的错误?

P.S.我使用VS2010。

+0

不确定是否更好地使用副本替换字符串本身是个好主意。 – rekire 2012-02-10 23:25:26

回答

14

这条线:

s.Remove((char) c); 

呼吁string.Remove(int) - 如果可以,编译器会经常使用,而不是一个扩展方法适用的实例方法。由于从charint的隐式转换,因此适用。这是抛出异常的方法,因为你传递它的参数超出范围。 (事实上​​,你是幸运的 - 在一个糟糕的情况将是范围,并返回完全意想不到的结果。)

一般来说我会强烈建议您不要创建具有相同的扩展方法名称作为扩展类型的实例方法,如果它们具有相同数量的参数,则为,特别是。一般来说,在不添加扩展方法的情况下,制定超载是非常困难的。不要忘记,只要不能轻易地计算出你的代码正在做什么,那么在一年的时间内读取代码的人将会有十倍的难度。

+2

只是**如果你在阅读之前回答了这些问题,我不知道。 o__o但+1,很好的答案。 :) – Mehrdad 2012-02-10 23:28:03

+0

@Mehrdad:在这种情况下,我很幸运;今晚的西翼情节(DVD)刚刚完成... – 2012-02-10 23:28:39

+0

哦,lolllllll好吧。 XD – Mehrdad 2012-02-10 23:29:27