Laden...

Beim Programmstart eine von zwei Methoden über einen Delegaten ausführen

Erstellt von mardem80 vor 6 Jahren Letzter Beitrag vor 6 Jahren 2.142 Views
M
mardem80 Themenstarter:in
11 Beiträge seit 2017
vor 6 Jahren
Beim Programmstart eine von zwei Methoden über einen Delegaten ausführen

Hallo,

ich möchte je nach Situation im Programm, jeweils eine von zwei Methoden über einen Delegaten
ausführen. Die entsprechende Definition des Delegaten sieht wie folgt aus:


private delegate void CreateAndDiscover();
private CreateAndDiscover delCreate;

Zuweisung einer Methode:


  //delegateCreate = createNewBluetoothInstance;  // <--- funktoniert nicht
delCreate = new CreateAndDiscover(createNewBluetoothInstance); //<--- funktioniert auch nicht!

Und der Aufruf sieht dann so aus:


        private void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            reportProgress(sender, 10, 1000);
            reportProgress(sender, 30, 500);

              delCreate();  //Aufruf der zugewiesenen Methode
            // createClientAndDiscoverDevices();

            reportProgress(sender, 70, 30);
            reportProgress(sender, 90, 500);
            reportProgress(sender, 100, 1000);
        }

Passieren tut nun leider gar nichts. Das Programm bleibt beim Laden hängen. Auch der Debugger hilft mir nicht weiter. Hat jemand eine Idee wo's hier hackt?

Gruß

T
2.224 Beiträge seit 2008
vor 6 Jahren

Wie sehen die beiden Methoden aus?
Normalerweise kann man ohne Probleme die von dir auskommentierte Version der Zuweisung verwenden.
Es kann nur nicht funktionieren, weil deine Methode nicht mit dem Aufbau des Delegate übereinstimmt.
Aber die entscheidenen Methoden fehlen, entsprechend kann man dies nicht beurteilen warum und was nicht klappt.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

M
mardem80 Themenstarter:in
11 Beiträge seit 2017
vor 6 Jahren

Ja stimmt, hab die Hälfte vergessen (copy & paste) 😃

Ich habe den Fehler gerade gefunden, da ich die falsche Methode an den Delegaten übergeben hatte!

Trotzdem Danke für deine Antwort!

2.207 Beiträge seit 2011
vor 6 Jahren

Hallo mardem80,

"Frage zu ..." ist niemals ein richtiger Titel für einen Thread. Er beschreibt dein Problem nicht. Bitte wähle vernünftige Titel, ich habe es mal nach bestem Wissen und Gewissen geändert. Kannst es gerne nochmal anpassen, wenn du magst.

Gruss

Coffeebean

3.003 Beiträge seit 2006
vor 6 Jahren

Ich habe den Fehler gerade gefunden, da ich die falsche Methode an den Delegaten übergeben hatte!

Naja, prinzipiell ist an dieser Stelle wirklich Quatsch, einen eigenen Delegaten zu deklarieren.


void UseDelegate(Action performAction)
{
    performAction();
}

UseDelegate(() => Console.WriteLine("hello"));
UseDelegate(() => MessageBox.Show("world"));

Mit anderen Worten: statt delegate void MyDelegate(); gibt es Action, die du einfach initialisieren kannst:


Action example = () => Log("Beispiel");

[Artikel] Delegaten, anonyme Methoden, Lambda-Ausdrücke & Co.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

T
2.224 Beiträge seit 2008
vor 6 Jahren

@LaTino
Wenn er aber den Delegaten austauschen will, dann macht es schon Sinn direkt den Delegaten zuzuweisen.
Ein Delegate ist schließlich ein Funktionszeiger, was das austauschen im Code vereinfacht und hier auch der Zweck ist.
Ob eine Action der bessere Ansatz wäre, darüber kann man streiten.
Ich würde hier auch ein Delegate bevorzugen.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

3.170 Beiträge seit 2006
vor 6 Jahren

Hallo,

Ob eine Action der bessere Ansatz wäre, darüber kann man streiten.
Ich würde hier auch ein Delegate bevorzugen.

@T-Virus
vorweg, ich denke, das was jetzt folgt, ist DIr alles bekannt.
Totzdem hast Du Dich da unglücklich ausgedrückt, daher hier nur zur Klarstellung für die Nachwelt:

Die Deklaration von Action lautet:

public delegate void Action();

Action IST also nichts anderes als ein Delegate.

Daher gibt es in der Verwendung auch absolut keinen Unterschied zwischen Action und einem beliebigen selbst definierten Delegaten ohne Parameter und Rückgabetypen.

Wenn man einen Delegaten definieren will, der keinen Parameter und keinen Rückgabewert hat, kann man sich das also in aller Regel sparen, weil es eben schon Action gibt.
Für parametrisierte Delegaten und Delegaten mit Rückgabetyp gibt es enstsprechende generische Ausprägungen von Action<...> und Func<...>.

EIgene Delegattypen braucht man nur, wenn die vordefinierten Varianten eben nicht ausreichen, oder man man unbedingt einen anderen Namen haben will (was natürlich durchaus auch sinnvoll sein kann, um die Semantik auszudrücken).

Ein Unterschied besteht aber darin, dass es sich bei jedem Delegaten um einen eigenen Typen handelt.
Habe ich also z.B. eine Funktion, die einen Delegaten annimmt, wird dieser Unterschied deutlich:

public void DoSomethingWithAction(Action action)
{
...
}

public delegate void MyDelegate();
public void DoSomethingWithMyDelegate(MyDelegate delegate)
{
...
}

public void TheMethodUsedForDelegate()
{
}

public void TheCallingMethod()
{
    Action action = TheMethodUsedForDelegate;
    MyDelegate myDelegate = TheMethodUsedForDelegate;

    // folgende Aufrufe funktionieren:
    DoSomethingWithAction(action);
    DoSomethingWithMyDelegate(myDelegate);

    // folgende Aufrufe funktionieren nicht (falscher Typ):
    DoSomethingWithAction(myDelegate);
    DoSomethingWithMyDelegate(action);

    // die verwendete Methode direkt zu übergeben, funktioniert aber für beide Aufrufe:
    DoSomethingWithAction(TheMethodUsedForDelegate);
    DoSomethingWithMyDelegate(TheMethodUsedForDelegate);   
}

Ähnlich verhält es sich bei genrischen Typeinschränkungen auf die Delegattypen.

Wenn man diese Typsicherheit haben will, braucht man also auch eigene Delegaten. Das ist aber IMO eher selten der Fall.
Im vorliegenden Beispiel aus dem Startpost sehe ich diesen Bedarf nicht.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

3.003 Beiträge seit 2006
vor 6 Jahren

Ein Delegate ist schließlich ein Funktionszeiger

Dann hast du das Konzept nicht verstanden. Delegaten sind mitnichten Funktionszeiger. Diese Erklärung wird gern verwendet, um das Konzept Leuten zu erklären, die wissen, was Funktionszeiger sind. Der Grund ist, dass beide Konzepte denselben Zweck erfüllen. Du kannst aber gern mal versuchen, in C++ mit Funktionszeigern multicasting abzubilden. Oder co- und Kontravarianz abbilden beim Zuweisen. Oder beim Verwenden als Methodenparameter.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

16.834 Beiträge seit 2008
vor 6 Jahren

Action IST also nichts anderes als ein Delegate.

Nicht 100%.
Eine Action ist ein multicast delegate.
Daher kann man mit Actions ziemlich fancy Zeugs machen, das ein simples Delegate so überhaupt gar nicht hergibt.

In .NET ist es aber so, dass alle Delegaten an für sich potentiell eine Multicast-Funktionalität haben.

Ich würde auch nicht sagen, dass Delegates keine Funktionszeiger sind; denn unter der Haube (also konzeptionell) sind sie genau das - eben mit weiteren Eigenschaften wie Multicast, Async/Sync....
Hab Delegates daher auch schon als "mehr als Funktionszeiger" bezeichnet.

Die CLR sieht die konzeptionelle Funktionalität auch vor bzw. hat sie, sodass man durchaus durch eine Anpassung des Compilers "echte" (finde kein passenderes Wort, klassische?) Funktionszeiger in C# einführen könnte.

3.170 Beiträge seit 2006
vor 6 Jahren

Hallo,

Nicht 100%.
Eine Action ist ein multicast delegate.
Daher kann man mit Actions ziemlich fancy Zeugs machen, das ein simples Delegate so überhaupt gar nicht hergibt.

Ich bleibe bei 100%, zumindest im Bereich C#/.NET, und darüber reden wir ja hier.
Was wäre sonst ein Beispiel für so ein simples Delegate?
Du schreibst ja selbst:

In .NET ist es aber so, dass alle Delegaten an für sich potentiell eine Multicast-Funktionalität haben. Da würde ich sogar "potentiell" streichen. Alle Delegates sind multicastfähig.

Siehe z.B. auch Multicast-Delegaten: Auswertung aller Rückgabewerte und Abbruchmöglichkeit.
Das funktioniert prinzipiell mit jedem Delegate. Ob eine Delegate multicast ist, hängt allein von der Verwendung ab.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

16.834 Beiträge seit 2008
vor 6 Jahren

Hab mit keinem Wort gesagt, dass Deine Aussage "falsch" sei.
In einem Gespräch, in dem man aber Delegaten nicht als Funktions- oder Methodenzeiger bezeichnen "darf", kann man dann halt auch nicht 100% sagen, dass Actions == simple Delegates sind.

AnyDotNetDelegate : System.MulticastDelegate : System.Delegate ist der Aufbau in .NET.
Prinzipiell sieht auch die Hierarchie hier ein technischen Unterschied vor; auch wenn alle Delegate-Typen in .NET eben (aktuell!) auf System.MulticastDelegate aufbauen.
Mir wäre jedenfalls spontan kein Delegate bekannt, das direkt auf System.Delegate basiert. Der Unterschied bleibt - und ich bleib dabei, dass die 100% in diesem Kontext nicht korrekt sind 😉

PS: übrigens gibt es hier auch erste Vorschläge neue Delegate-Arten und auch Single- sowie Static Delegates in die Sprache zu übernehmen.
Proposal: Struct Lambdas
Static Delegates

Im Hinblick der Performance und die Richtung, die .NET Core schlägt (und auch C# 8.0) ist das gar nicht so unwahrscheinlich, dass das kommt.

3.170 Beiträge seit 2006
vor 6 Jahren

Hallo,

AnyDotNetDelegate : System.MulticastDelegate : System.Delegate ist der Aufbau in .NET.

Ja, so gesehen schon. Allerdings ist das für den Benutzer von Delegaten nicht relevant,
denn die Doku sagt dazu:

The T:System.Delegate class is the base class for delegate types. However, only the system and compilers can derive explicitly from the T:System.Delegate class or from the T:System.MulticastDelegate class. It is also not permissible to derive a new type from a delegate type.

Most languages implement a delegate keyword, and compilers for those languages are able to derive from the T:System.MulticastDelegate class;

Das ist also alles (zumindet momentan) reine Infrastruktur, an die man als Benutzer niemals drankommt, ohne sich den Compiler anzupassen.

Mir wäre jedenfalls spontan kein Delegate bekannt, das direkt auf System.Delegate basiert.

Den wird es Aufgrund des aus der Doku zitierten Sachverhalts wohl auch nicht geben.

Der Unterschied bleibt - und ich bleib dabei, dass die 100% in diesem Kontext nicht korrekt sind 😉

Aufrgund der puren Existenz von System.Delegate: einverstanden.
Erzeugen kann man sowas aber nicht, und eine Relevanz für den Benutzer von Delegaten ist damit IMO auch nicht gegeben.

Dann können wir uns vielleicht darauf einigen, dass kein Unterschied zwischen Action und irgendwelchen anderen Delegattypen besteht, die man zu Zeit im Code erzeugen oder direkt benutzen kann.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca