Wat maakt een naam van een methode equivalent aan een actiedelegate?

Ik was gewoon aan het experimenteren en eindigde met het volgende fragment:

public static class Flow {
    public static void Sequence(params Action[] steps) {
        foreach (var step in steps)
            step();
    }
}
void Main() {
    Flow.Sequence(() => F1(),() => F2());
    Flow.Sequence(F1, F2);//<-- what makes this equiv to the line above?

}
void F1() { }
void F2() { }

Ik realiseerde me niet dat de naam van een methode alleen hetzelfde was als een actie.

Wat maakt dit zo?

5
Ze zijn niet echt equivalent; Dit laatste is beter, omdat het een extra, lege methodeaanroep vermijdt. (wat ik toegeef is misschien geoptimaliseerd, maar toch, ze zijn niet equivalent)
toegevoegd de auteur Andrew Barber, de bron

3 antwoord

In C# zijn afgevaardigden niets meer dan methode-aanwijzers . Ze kunnen verwijzen naar bestaande methoden in een klasse, of onafhankelijke anonieme gedelegeerde objecten helemaal.

Deze paragraaf van de bovenstaande link moet uitleggen wat er in uw code gebeurt:

Elke methode die overeenkomt met de handtekening van de gedelegeerde, die bestaat uit het retourneringstype en de parameters, kan worden toegewezen aan de gedelegeerde. Dit maakt het mogelijk om methodeaanroepen programmatisch te wijzigen en ook nieuwe code in bestaande klassen in te pluggen. Zolang u de handtekening van de gedelegeerde kent, kunt u uw eigen gedelegeerde methode toewijzen.

Dat wil zeggen dat bij het oplossen van typen afgevaardigden, wat wordt beschouwd hun handtekeningen zijn, in plaats van hun namen.

In uw geval hebben uw F1() en F2() methoden, die geen parameters innemen en niets terugsturen, overeenkomstige handtekeningen met het parameterloze Actie delegeren :

public delegate void Action();

Daarom zijn ze impliciet converteerbaar in Action .

Als u een methode met een ander retourneringstype of ten minste één parameter probeert door te geven, krijgt u een compileerfout omdat deze niet overeenkomt met de handtekening van Actie .

7
toegevoegd
@xixonia: Niet erg "direct", de compiler maakt ook een exemplaar van Actie , deze Actie wordt direct aangemaakt met de methode F1 . Tijdens het gebruik van () => F1() , wordt de actie gemaakt op basis van een anonieme methode, waarbij F1() wordt aangeroepen.
toegevoegd de auteur Danny Chen, de bron
En , roept met behulp van F1 in plaats van () => F1() de methode rechtstreeks op in plaats van er een extra deelnemer aan toe te voegen.
toegevoegd de auteur cwharris, de bron
@DannyChen, Tenminste meer direct dan niet. :) Dankje voor de correctie. Ik was bang dat ik dat niet correct had gezegd.
toegevoegd de auteur cwharris, de bron

Kortom, dit is een beetje van wat er gebeurt op de achtergrond:

void Main() 
{    
    Flow.Sequence(new Action(delegate(){ F1(); }), new Action(delegate(){ F2(); }));    
    Flow.Sequence(new Action(F1), new Action(F2)); 
}

Ze zijn niet PRECIES equivalent, maar ze zijn heel dichtbij. Ze zouden dezelfde resultaten opleveren tijdens runtime, het enige verschil is dat de argumenten in de eerste Sequence-aanroep een actie zou zijn die een anonieme methode aanroept die dan de statische methoden F1 en F2 aanroept; de tweede Sequence-aanroep zou een Actie zijn die de statische methoden F1 en F2 oproept.

Ik hoop dat dit helpt.

3
toegevoegd
Geen zorgen, ik heb het voor je opgelost.
toegevoegd de auteur BoltClock, de bron
Excuseer de opmaak ... met een mobiel apparaat. :-P
toegevoegd de auteur Kevin Carrasco, de bron

De compiler gebruikt een impliciete conversie van een methodegroep naar een gedelegeerde van het compatibele type (in dit geval een ongeldige retourneermethode zonder argumenten), de methode-namen zijn hier niet relevant.

0
toegevoegd