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

C # provides the following signature characteristics that will be used when overloading functions.

We know that only arguments are taken into account for overloading; their number and types, but the purpose of polymorphism is to provide the same name, but different uses depending on the calling strategy.

If I have a class containing two methods with the same name and signature, while one is static and the other is not, the C # compiler throws an error; "The class already defines a member named" foo "with the same parameter types." The call to both methods will be different; one with the name of the object and static with the name of the class. Consequently, there is no ambiguity with the challenge strategy. Then why gives an error?

class Example { public void foo() { } public static void foo() { } } class Program { static void Main(string[] args) { Example e = new Example(); e.foo(); } } 
+11
source share
5 answers

The reason the error occurs is because static methods can be called from non-static methods without specifying a type name. In this case, the compiler will not 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 STATUS message regarding your case. You can also check it out.

+13
source

This error occurs because this is how behavior is defined in C # Language Specification . Any "ambiguous" use (or methods of eliminating the ambiguity of these) does not matter, although such reasoning and edge cases may have led designers to prevent explicit resolution of this differentiation .. or it could just be C # encoding for the base. NET CLI / CLR Restriction 1 .

From "3.6 Signatures and Overloading" in the C # specification (and according to related documentation), formatted as bullets:

Method signature consists of

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

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

And, from the "1.6.6 Methods" we have a limitation and a consensus summary:

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

This restriction applies to (and regardless of) the method considered for polymorphism.

Also, as a final note: instance methods must be virtual or accessible through an interface that must be polymorphic at run time in C #. (Both methods of hiding and overloading the method may be a form of compile-time polymorphism, but that's a different topic ..)


1 There is support for this, simply resulting from a limitation of the CLI / CLR.NET itself, which should not be bypassed (i.e. for compatibility reasons). From "I.8.6.1.5 Method Signatures" in ECMA-335 :

Method signature consists of

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

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

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

Thus, the intersection between the components of the C # / CLS and ECMA signature is the name of the method, the “number of common parameters” and the “list of zero or more parameter signatures”.

+5
source

I feel your question: “Why did the standard decide to prohibit declaring two methods that differ only in the static keyword?”, And therefore the answer “because the standard says so” does not suit me.

Now the problem is that there may be some reason. The standard is the Law, and it can be arbitrary. Without the help of someone involved in the development of the language, all we can do is reflect on the reasons, trying to uncover the spirit of the Laws.

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

Because they speak other languages.

C ++ and Java are inspirational languages ​​for C #, and it makes sense to observe the same overload rules as these languages. As to why this is so in these languages, I do not know. I found a similar question about SO about C ++ , although there is no answer to the question of why this is so (outside the "standard says so").

Because it creates an ambiguity that needs to be resolved.

As noted by others and OPs that allow the same signatures excluded for a static keyword, they force the user to invoke methods explicitly (by prefixing the class name or instance name). This adds a level of complexity to the code. Of course, this can already be done with fields and parameters. However, some of them disagree with this use and prefer to choose different names (field prefix with _ or m_) for the fields.

Because it does not make much sense in OOP.

This is really my understanding here, so I can be completely wrong (at least @ user2864740 thinks the argument is dubious - see comments), but I feel that static members are a way of introducing “functional programming” into OOP, They don’t are tied to a specific instance, so they do not change the internal state of the object (if they change the state of another object, then they must be a non-stationary method of this other object), so they are "clean". Therefore, I do not understand how a “pure function” can be semantically close to a regular object, so that they will have the same name.

+3
source

The same question was asked to Eric Gunnerson , who worked in the C # language development team, and he answered:

It is true that there would be no ambiguity between the two functions with regard to the compiler. However, there is considerable potential for confusion on the part of the user. It would be difficult to find the correct method in the documentation, and once you have done this, it is difficult to be sure that you are invoking the correct version (that is, you can accidentally invoke the static version when you want the instance version).

Therefore, the reason this is not allowed is design.

+1
source

Check out this simple pseudo code:

 class A { public void B(){...} public static void B(){...} } ... AA = new A(); AB(); // <== which one is going to be called? 
-1
source

Source: https://habr.com/ru/post/1202213/


All Articles