C # Il possibile nome del metodo è in conflitto con i parametri opzionali: perché non è vietato? [chiuso]

4

Abbiamo una semplice classe e il metodo principale:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Rextester
{
public class Program
{
    public static void Main(string[] args)
    {
       bar bar = new bar();
        bar.foo("a");
    }
}

public class bar
{
    public void foo(String a, String b = "b")
    {
        Console.WriteLine("Foo1");            
    }       

}
}

Questo scriverà

Foo1

nella console.

Ora, aggiungiamo un sovraccarico del metodo nella classe, utilizzando parametri facoltativi :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Rextester
{
public class Program
{
    public static void Main(string[] args)
    {
       bar bar = new bar();
        bar.foo("a");
    }
}

public class bar
{
    public void foo(String a, String b = "b")
    {
        Console.WriteLine("Foo1");            
    }

     public void foo(String a)
    {
        Console.WriteLine("Foo2");            
    }


}
}

Questo scriverà

Foo2

nella console.

Mi aspettavo errore nella compilazione perché mi aspetto che foo (String a, String b="b") rappresenti sia foo (String a) che foo (String a, String b) signature, a causa dei parametri opzionali. Ma mi sbagliavo. Perché è permesso?

    
posta boucekv 14.03.2017 - 18:22
fonte

2 risposte

4

Per iniziare con un importante preventivo di Eric Lippert

A lot of people seem to think that this:

void M(string x, bool y = false) { … whatever … }

is actually a syntactic sugar for the way you used to have to write this in C#, which is:

void M(string x) { M(x, false); }
void M(string x, bool y) { … whatever … }

But it is not. The syntactic sugar here is not on the declaration side, but rather on the call side. There is only one method; when you make a call that omits optional arguments, the compiler simply inserts the arguments at the call site. That is:

M(“hello”);

is rewritten as

M(“hello”, false);

Suggerirei di leggere l'intera serie per comprendere veramente l'implementazione di argomento facoltativo da parte di C # come la riscrittura del sito di chiamata. Fondamentalmente la tua aspettativa

I expect that foo(String a, String b = "b") represents both foo(String a) and foo(String a, String b) signature

Non è come funziona. Invece foo(String a, String b = "b") rappresenta effettivamente solo foo(String a, String b) . Un esempio che Eric Lippert fornisce perché il tuo intution non funzionerebbe, supponiamo che abbiamo avuto foo(String a = "a", String b = "b") . In questo caso non è possibile generare bene foo(String) .

Ecco perché foo(String a, String b = "b") e foo(String a) possono appartenere legittimamente alla stessa classe (perché il parametro facoltativo è compilato per i chiamanti anziché modificare la dichiarazione). Sebbene sia un risultato naturale dell'implementazione di parametri facoltativi, è chiaramente anche soggetto a errori, quindi c'è ancora una domanda sul perché non sia disabilitato.

Non ho una risposta definitiva qui, e in realtà solo le persone coinvolte nello sviluppo di C # potrebbero dire, ma per parafrasare Eric Lippert altrove, ogni caratteristica di una lingua ha un costo di implementazione; le caratteristiche che i progettisti non ritengono valgano il costo, non vengono implementate. In questo caso, rendere illegale questo codice probabilmente errato è una caratteristica con un costo definito e solo vantaggi marginali (le persone stanno davvero mescolando paramter e override facoltativi in questo modo?) Quindi non viene implementato.

    
risposta data 15.03.2017 - 07:40
fonte
1

Quando scrivi una chiamata al metodo, il compilatore determinerà quale metodo viene chiamato con quali parametri. Ci sarà una fase in cui il compilatore determina tutti i metodi che potrebbero essere chiamati, quindi si lamenta se il numero è zero, e cercherà di determinare il migliore da chiamare se ce n'è più di uno, lamentarsi se non può decidere.

In questo caso, la lingua ha una regola che preferisce una funzione con meno parametri. Personalmente non penso che questa sia una buona regola, ma Microsoft non è d'accordo con la mia opinione. Ti sei sovraccaricato come

public func foo (String a, String c = "c")

avresti ricevuto un avvertimento.

    
risposta data 15.03.2017 - 08:19
fonte

Leggi altre domande sui tag