为什么Enum上的HasFlag扩展方法胜过Enum.HasFlag?

cit*_*att 5 c# extension-methods enums

如果我在Enum上创建了一个扩展方法HasFlag,每当我尝试调用HasFlag枚举实例时,它都会使用扩展方法,而不是实例方法.为什么?

public static class Extensions
{
  public static bool HasFlag(this Enum e)
  {
    return false
  }
}
Run Code Online (Sandbox Code Playgroud)

使用代码:

public enum Foo
{
  A, B, C
}

public void Whatever()
{
  Foo e = Foo.A;
  if (e.HasFlag())
  {
    // ...
  }
}
Run Code Online (Sandbox Code Playgroud)

编译为:

public void Whatever()
{
  Foo e = Foo.A;
  if (Extensions.HasFlag(e))
  {
    // ...
  }
}
Run Code Online (Sandbox Code Playgroud)

为什么编译器不使用Enum.HasFlag实例方法?

Beh*_*zad 1

扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,但它们的调用方式就像扩展类型上的实例方法一样。对于用 C# 和 Visual Basic 编写的客户端代码,调用扩展方法和调用类型中实际定义的方法之间没有明显区别。

扩展方法不能覆盖实例主方法,并且它不知道要调用哪个方法:

以下方法之间的调用是不明确的

解决这个问题的唯一方法是使用正常的静态方法语法调用扩展方法。所以代替这个:

e.HasFlag();
Run Code Online (Sandbox Code Playgroud)

你必须这样做:

Extensions.HasFlag(e);
Run Code Online (Sandbox Code Playgroud)

但是如果你在扩展方法中添加其他参数,那么它与主方法不一样,所以当你调用HasFlag方法时,实际上调用的是扩展方法。例如:

public static bool HasFlag(this Enum e, bool isNullable)
{
    return false;
}
Run Code Online (Sandbox Code Playgroud)

参考:

扩展方法(C# 编程指南)

C# 中的扩展方法、空值、命名空间和优先级