Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

164
Visualizações
Why are these two methods not ambiguous?

This is the signature for the Ok() method in ApiController:

protected internal virtual OkResult Ok();

And this is my method from my RestController class (which extends from ApiController):

// Note that I'm not overriding base method
protected IHttpActionResult Ok(string message = null);

Since OkResult implements IHttpActionResult, both of these methods can be called like this:

IHttpActionResult result = Ok();

In fact, that's what I'm doing in my application.

My class PersistenceRestController (which extends from RestController), has these lines of code:

protected override async Task<IHttpActionResult> Delete(Key id)
{
    bool deleted = //... Attempts to delete entity
    if(deleted) return Ok();
    else return NotFound();
}

This compiles fine, and no warning is raised about method ambiguity. Why is that?

PersistenceRestController has also inherited the protected methods from ApiController so it should have both versions of Ok() (and it does).

At execution, the method executed is the one from my RestController.

How does the compiler know which method to run?

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

Jon Skeet answered a similar question (without the inheritance complication) here:

When the compiler has two otherwise-equal options to choose from, it will use an overload which doesn't need use any unsupplied optional parameters in preference to one that does...

In your case, however, the method from the RestController is being chosen because it's the more derived class. Jon does a good job of addressing the topic in detail in his book C# in Depth -- look at the inheritance section of that page, which essentially states that the compiler will prefer a method on the actual instance class before methods on less derived classes.

over 4 years ago · Santiago Trujillo Relatório

0

EDIT:

I am leaving my original answer for posterity because I think it lets you visualize things, but DO NOT BE CONFUSED! The compiler does not actually treat the optional parameter as syntactic sugar for an overridden method. It treats it as a single method with an optional parameter. Dusty's answer, mentioning that "the method from the RestController is being chosen because it's the more derived class," is correct.

ORIGINAL (With visible edits for correctness):

Because they are NOT ambiguous. In order to be ambiguous the methods need to have the same signature. The fact that the string message parameter has a default value of null effectively creates BEHAVES as though it creates two callable overrides, one of which HIDES the original method, and one of which is distinctly callable with a string.

You are effectively doing creating the same behavior as if you were to do this:

public class RestController : ApiController
{
    protected new OkResult Ok()
    {
        return Ok(null);
    }

    protected OkResult Ok(string message)
    {
        // Do your thing...
    }
}

You will find there is no way to directly call ApiController.Ok() from PersistenceRestController.

If you want to call ApiController.Ok() from RestController, you'll have to use the base keywoard: base.Ok();

over 4 years ago · Santiago Trujillo Relatório

0

While @DimitarTsonev and @Dusty are telling true stuffs, but your answer is something between their answers. Here, you have inheritance situation. See these classes:

public class Foo {
    public void Bar() {
    }
}

public class Foo2 : Foo{
    public void Bar(string message = null) {
    }
}

public class Foo3 : Foo2{
    public void Test(){
        Bar();
    }
}

When you call Bar() in your Foo3 class, the runtime will lookup after the method inside the Foo3 class. If found it, execute it, otherwise go to the top class: Foo2 and look after Bar method. Is there any? yes! so execute it! that's why when you call Ok, your RestControllers' version get executed.

But also, the Foo2.Bar(string message = null) will not conflict with Foo.Bar() because they are NOT ambiguous as @DimitarTsonev said. So, your code will work just fine.

AND, what about calling Foo.Bar() from Foo3? You have to use casting here:

public class Foo3 : Foo2 {
    public void Test() {
        Bar(); // this will execute Foo2.Bar()
    }
    public void Test2() {
        ((Foo)this).Bar(); // this one will execute Foo.Bar()
    }
}
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda