为什么我在扩展方法中的 `char` 参数被解释为 `int`?

Why is my `char` argument in an extension method interpreted as `int`?

我为 string.

编写了一个带有非常简单扩展方法的 .DLL 库

我的方法 - .Remove(char deletedChar),删除 string 中出现的所有 char。这会重载默认的 .Remove(int startIndex) 方法。但是,当我想使用它时,会调用 .Remove(int startIndex) 而不是我的方法,尽管我将 char 作为参数。

我的意思是,给定这段代码:

string Test = "12-34-56-78-90-123-456-789-0123-4567-89012-34567-890123-456789-000000";
MessageBox.Show(Test.Remove('-'));

我的预期结果是:

1234567890123456789012345678901234567890123456789000000

然而,实际结果是:

12-34-56-78-90-123-456-789-0123-4567-89012-34

在屏幕截图上查看:

这意味着,我的 char '-' 被解释为它的 ASCII 值 (45),这是删除字符串的起始索引。

为什么会这样?即使将 char 转换为 char(即 (char)'-')也无​​法解决问题。我知道我可以简单地重命名扩展方法,但我仍然不明白为什么会这样。有人可以解释这种现象或指出解释它的文档吗?

粘贴我的扩展方法以防有人想要使用它:

    /// <summary>
    /// Removes all occurences of specified char.
    /// </summary>
    /// <param name="str"></param>
    /// <param name="deletedChar">The char you want to remove.</param>
    /// <returns>string without the specified char.</returns>
    public static string Remove(this string str, char deletedChar)
    {
        for (int i = 0; i < str.Length; i++)
        {
            if (str[i] == deletedChar)
            {
                str = str.Remove(i, 1);
                i--;
            }
        }
        return str;
    }

C# 实例方法在找到扩展之前被调用。

来自documentation

When the compiler can't find an instance method with a matching signature, it will bind to a matching extension method if one exists.

写这个helperclass,我们可以看到调用的好方法是:

public static class StringHelper
{
  public static string MyRemove(this string str, int index)
  {
    return "remove at index";
  }
  public static string MyRemove(this string str, char code)
  {
    return "remove all chars";
  }
}

测试

Console.WriteLine("".MyRemove(1));
Console.WriteLine("".MyRemove('a'));

输出

remove at index
remove all chars

因此解决方案是使用专用方法的名称:

public static class StringHelper
{
  public static string RemoveAll(this string str, char deletedChar)
  {
    for ( int i = 0; i < str.Length; i++ )
    {
      if ( str[i] == deletedChar )
      {
        str = str.Remove(i, 1);
        i--;
      }
    }
    return str;
  }
}

因此设计和使用更加清晰明了,同时参数的类型告诉我们要删除什么。

但是这种方法没有优化,例如可以替换为:

public static string RemoveAll(this string str, char code)
{
  return str.Replace(code.ToString(), "");
}

或者这个比较好:

using System.Text;

public static string RemoveAll(this string str, char code)
{
  var builder = new StringBuilder();
  foreach ( char c in str )
    if ( c != code )
      builder.Append(c);
  return builder.ToString();
}

或使用 Linq,但可能不如以前优化:

using System.Linq;

public static string RemoveAll(this string str, char code)
{
  return new string(str.Where(c => c != code).ToArray());
}