Why can't a static and non-static method share the same signature?

Reason why it is throwing an error is that static methods can be called from non-static methods without specifying type name. In this case, compiler won't be able to determine, which method is being called.

public class Foo()
{
   public static void MyMethod() {};
   public void MyMethod() {}

   public void SomeOtherMethod()
   {
      MyMethod(); // which method we're calling static or non-static ?
   }
}

EDIT

Just found this SO post regarding your case. You might want to check it also.


This error occurs because this is how the behavior is defined in the C# Language Specification. Any "ambiguous" usage (or ways to disambiguate such) is irrelevant, although such reasoning and edge-cases may have led the designers to not explicitly allow such a differentiation .. or it might simply be a C# codification of an underlying .NET CLI/CLR restriction1.

From "3.6 Signatures and overloading" in the C# specification (and in agreement with the linked documentation), formatted as bullets:

The signature of a method consists of

  • the name of the method,
  • the number of type parameters, and
  • the type and kind (value, reference, or output) of each of its formal parameters ..

Method modifiers, including static, are not considered as part of the method signature here.

And, from "1.6.6 Methods" we have the restriction and an agreeing summary:

The signature of a method must be unique in the class in which the method is declared. The signature of a method consists of the name of the method, the number of type parameters and {the number, modifiers, and types of} its parameters..

This restriction applies before (and independently of) the method being considered for polymorphism.

Also, as a closing note: instance methods must be virtual or accessed through an interface to be run-time polymorphic in C#. (Both method hiding and method overloading are arguably a form of compile-time polymorphism, but that's another topic..)


1There is support for this simply being the result of a restriction of the .NET CLI/CLR itself that is not worth bypassing (ie. for interoperability reasons). From "I.8.6.1.5 Method signatures" in ECMA-335:

A method signature is composed of

  • a calling convention [CLS Rule 15: "the only calling convention supported by the CLS is the standard managed calling convention"],
  • the number of generic parameters, if the method is generic,
  • [omitted rule]
  • a list of zero or more parameter signatures—one for each parameter of the method— and,
  • a type signature for the result value, if one is produced.

Method signatures are declared by method definitions. Only one constraint can be added to a method signature in addition to those of parameter signatures [CLS Rule 15: "The vararg constraint is not part of the CLS"]:

  • The vararg constraint can be included to indicate that all arguments past this point are optional. When it appears, the calling convention shall be one that supports variable argument lists.

The intersection between the C#/CLS and ECMA signature components is thus the method name, "the number of generic parameters", and "a list of zero or more parameter signatures".


I feel your question is "why did the standard choose to forbid declaring two methods that differ only by the static keyword?", and therefore the answer "because the standard says so" does not look appropriate to me.

Now, the problem is, there could be any reason. The standard is the Law, and it can be arbitrary. Without the help of somebody who participated to the language's design, all we can do is speculate about the reasons, trying to uncover the spirit of the Laws.

Here is my guess. I see three main reasons for this choice:

Because other languages say so.

C++ and Java are inspirational languages for C#, and it makes sense to observe the same overloading rules as those languages. As to why it is this way in these languages, I don't know. I found a similar question on SO about C++, although no answer is given as to why it is this way (outside of "the standard says so").

Because it creates ambiguity that need to be resolved.

As others and OP noted, allowing the same signatures excepted for the static keyword forces the user to call the methods in an unambiguous way (by prefixing the class name or the instance name). This adds a level of complexity to the code. Of course this can already be done with fields and parameters. However some don't agree with this usage and prefer to choose different names (prefixing the fields with _ or m_) for the fields.

Because it does not make a lot of sense in OOP.

This is really my understanding here, so I could be completely wrong (at least @user2864740 thinks that the argument is dubious -- see comments), but I feel like static members are a way to introduce "functional programming" in OOP. They are not bound to a specific instance, so they don't modify the internal state of an object (if they modify the state of another object, then they should be a non-static method of this other object), in a way they are "pure". Therefore I don't understand how a "pure function" could be semantically close enough of a regular object method so that they would share the same name.