A maneira do C# funcionar é muito interessante, além de lógica. Vejam esse caso. Se tenho esta classe:

public class Classe
{
    public static string Estatico(object o)
    {
        return Metodo(o);
    }
    private static string Metodo(string s)
    {
        return "string";
    }
    private static string Metodo(object o)
    {
        return "object";
    }
}

Independente do parâmetro que eu passar para o método “Estático”, ele sempre vai chamar o método “Metodo” com parâmetro object. O que recebe parâmetro string nunca será chamado. Isso acontece porque o binding da chamada acontece em tempo de compilação, e a IL escrita identifica claramente que o método chamado é parâmetro object, já que o com parâmetro string não atende. Ao chamar o método em runtime e passar uma string, a ligação entre o método “Estatico” e “Metodo(object)” já está feita.

Estes testes servem pra confirmar isso:

[TestMethod]
public void EstaticoString()
{
    Assert.AreEqual("object", Classe.Estatico(""));
}
[TestMethod]
public void EstaticoObject()
{
    Assert.AreEqual("object", Classe.Estatico(1));
}

Existe alguma maneira de fazer com que o método que recebe uma string seja chamado? Existe. Desde que o C# incorporou características dinâmicas, em sua versão 4, é possível atrasar a resolução do overload escolhido para o tempo de execução, deixando de fazê-la em tempo de compilação. Assim, se quisermos que isso aconteça só quando a aplicação estiver rodando, basta trocar o tipo do parâmetro do método “Estatico” de object pra dynamic. Eu preferi criar outro método:

public static string Dinamico(dynamic d)
{
    return Metodo(d);
}

Esse método não sabem qual overload está sendo chamado em tempo de compilação. Isso só é resolvido quando a aplicação está rodando. Nesse momento, é possível perceber que o parâmetro é uma string e chamar o overload apropriado.

Aqui os testes:

[TestMethod]
public void DinamicoString()
{
    Assert.AreEqual("string", Classe.Dinamico(""));
}
[TestMethod]
public void DinamicoObject()
{
    Assert.AreEqual("object", Classe.Dinamico(1));
}

Interessante, não?

Coloquei todo o código no gist. Vejam lá, comentem, forkem, baixem, divirtam-se.

Giovanni Bassi

Arquiteto e desenvolvedor, agilista, escalador, provocador. É fundador e CSA da Lambda3. Programa porque gosta. Acredita que pessoas autogerenciadas funcionam melhor e por acreditar que heterarquia é mais eficiente que hierarquia. Foi reconhecido Microsoft MVP há mais de dez anos, dos mais de vinte que atua no mercado. Já palestrou sobre .NET, Rust, microsserviços, JavaScript, TypeScript, Ruby, Node.js, Frontend e Backend, Agile, etc, no Brasil, e no exterior. Liderou grupos de usuários em assuntos como arquitetura de software, Docker, e .NET.