We talked today, with Miha, a C# Yoda. Via IM, everything seemed pointless. Couldn't find a good case for the cause of the following mind experiment:
using System;
class Tubo
{
public static void Test() {}
private void Test() {}
}
Note: I'm using Miha's syntax in this post.
We have a static method called Test and an instance method, also called Test. Parameter models of both methods are the same, empty.
Would this compile?
It does not.
The question is why and who/what causes this. There is actually no rationale behind not allowing this thing to compile since both, the compiler and the runtime know the method info upfront.
Since the runtime has all the information it needs, it is strange that this would not be allowed at compile time. However, a (C#) compiler has to determine whether you, the programmer meant to access a static or an instance method.
Here lie the dragons.
It is illegal in most virtual machine based languages to have the same method name and signature for a static/instance method.
The following is an excerpt from a Java specification:
8.4.2 Method Signature
Two methods have the same signature if they have the same name and argument types.
Two method or constructor declarations M and N have the same argument types if all of the following conditions hold:
- They have the same number of formal parameters (possibly zero)
- They have the same number of type parameters (possibly zero)
- Let <A1,...,An> be the formal type parameters of M and let <B1,...,Bn> be the formal type parameters of N. After renaming each occurrence of a Bi in N's type to Ai the bounds of corresponding type variables and the argument types of M and N are the same.
Java (and also C#) does not allow two methods with the same name and parameter model no matter what the access modifier is (public, private, internal, protected ...) and whether the method is static or instance based.
Why?
Simple. Programmer ambiguity. There is no technical reason not to allow it.
Consider the following:
using System;
class Tubo
{
public static void Test();
private void Test();
public void AmbiguousCaller() { Test(); }
}
What would method AmbiguousCaller call? A static Test or instance Test method?
Can't decide?
That's why this is not allowed.
And yes, it would call the instance method if this would be allowed, since statics in C# should be called using a class name, as in Test.Test(). Note that the preceding example does not compile. Also note, that it is legal to have a AmbiguousCaller body as Test() or Tubo.Test().
There is another ambiguous reason. Local variables in C# cannot be named the same as the enclosing class. Therefore, this is illegal:
using System;
class Tubo
{
private int Tubo;
}
It is. Do a csc /t:library on it.
Since you confirmed this fact, consider the following:
using System;
public class Tubo
{
public static void StaticMethod() {}
public void InstanceMethod() {}
}
public class RunMe
{
public static void Main()
{
Tubo Tubo = new Tubo();
Tubo.InstanceMethod();
Tubo.StaticMethod();
}
}
Focus on the Main method body. In Tubo.InstanceMethod() an instance method is called and a reference (namely Tubo) is used. In Tubo.StaticMethod() a static method is called and Tubo is not an instance reference, but class name.
It all comes down to programmer ambiguity. Given a chance, I would support this design decision too.