Variable als Verknüpfung als Argument übergeben

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 29 Antworten in diesem Thema. Der letzte Beitrag () ist von siycah.

    @kafffee Nullable(Of Any) ist vergleichbar mit dem Pointer in C / C++.
    Das ist im Prinzip ein Zeiger auf einen Speicherplatz des Types.
    Ist der Nothing, geht nix.
    Zeigt er in verwalteten Speicher, hast Du Zugriff auf die Variable.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Kafffee, ich glaube nicht das es hilfreich für dich wäre das auf dein Bedürfniss zuzuscheiden. Du musst das verstehen um es anwenden zu können. Ich habe mir trotzdem nochmal die Mühe geamcht und ein weiteres Beispiel gemacht, diesmal in VB und mit ein paar Kommentaren. Wenn du das dann immer noch nicht verstehst, schieb das auf eine ToLearn-Liste und versuch es später noch mal. Manchmal sieht man einfach den Wald vor lauter Bäumen nicht mehr. Ab und zu hab ich auch solche "blockaden".

    Damit du siehst, wie die Funktionen genutzt werden, mach 3 Haltepunkte rein und führe das mal aus.
    Die Haltepunkte in den Zeilen 19, 25 und 29

    VB.NET-Quellcode

    1. Imports System.Threading
    2. Imports TheDelegates.KlasseMitDelegates
    3. Class MainWindow
    4. Dim Klasse As New KlasseInDerWirFunktionenInDerMainWindowInstanzBenutzen(
    5. New TellMeWhenLikeWithAnEvent(AddressOf HabeFertig),
    6. New MathematischeFunktionMit_2_IntegerFürParameter(AddressOf Addieren),
    7. New MathematischeFunktionMit_2_IntegerFürParameter(AddressOf Multiplizieren))
    8. Public Sub New()
    9. ' This call is required by the designer.
    10. InitializeComponent()
    11. ' Add any initialization after the InitializeComponent() call.
    12. Klasse.StarteArbeit()
    13. End Sub
    14. Public Sub HabeFertig()
    15. MessageBox.Show("Habe fertig")
    16. Klasse.NutzeAddierFunktion()
    17. Klasse.NutzeMultiplizierFunktion()
    18. End Sub
    19. Public Function Addieren(c As Integer, d As Integer)
    20. Return c + d
    21. End Function
    22. Public Function Multiplizieren(e As Integer, f As Integer)
    23. Return e * f
    24. End Function
    25. End Class
    26. Class KlasseInDerWirFunktionenInDerMainWindowInstanzBenutzen
    27. Public DelegateSubFürFertig As TellMeWhenLikeWithAnEvent
    28. Public DelegateFunktionAddition As MathematischeFunktionMit_2_IntegerFürParameter
    29. Public DelegateFunktionMultiplikation As MathematischeFunktionMit_2_IntegerFürParameter
    30. Public Sub New(zeigerAufSub As TellMeWhenLikeWithAnEvent,
    31. addierFunktion As MathematischeFunktionMit_2_IntegerFürParameter,
    32. multiplizierFunktion As MathematischeFunktionMit_2_IntegerFürParameter)
    33. DelegateSubFürFertig = zeigerAufSub
    34. DelegateFunktionAddition = addierFunktion
    35. DelegateFunktionMultiplikation = multiplizierFunktion
    36. End Sub
    37. Public Sub StarteArbeit()
    38. For i As Integer = 0 To 4
    39. Debug.WriteLine(i)
    40. Thread.Sleep(1000)
    41. Next
    42. DelegateSubFürFertig.Invoke() 'hier wird die Sub HabeFertig in der MainWindow instanz genutzt
    43. End Sub
    44. Public Sub NutzeAddierFunktion()
    45. Dim a As Integer = 1
    46. Dim b As Integer = 2
    47. Dim ergebnis As Integer = DelegateFunktionAddition.Invoke(a, b) ' hier wird die funktion Addieren in MainWindow instanz genutzt
    48. MessageBox.Show(ergebnis.ToString())
    49. End Sub
    50. Public Sub NutzeMultiplizierFunktion()
    51. Dim a As Integer = 1
    52. Dim b As Integer = 2
    53. Dim ergebnis As Integer = DelegateFunktionMultiplikation.Invoke(a, b) ' hier wird die funktion Multiplizieren in MainWindow instanz genutzt
    54. MessageBox.Show(ergebnis.ToString())
    55. End Sub
    56. End Class
    57. 'packen wir das mal in eine andere Klasse, diese delegaten können die adressen der Subs/Funktionen speichern
    58. Public Class KlasseMitDelegates
    59. 'Die Subs die man hier drin "speichern" kann müssen parameterlos sein
    60. 'Die Signaturen müssem also übereinstimmen
    61. Public Delegate Sub TellMeWhenLikeWithAnEvent()
    62. 'Man kann aber auch delegaten für Funktionen haben
    63. 'die siganturen müssen auch übereinstimmen
    64. Public Delegate Function MathematischeFunktionMit_2_IntegerFürParameter(a As Integer, b As Integer) As Integer
    65. 'so muss dann die Signatur der Funktion aussehen, der Name is egal
    66. 'Public Function Addiere(x As Integer, y As Integer) As Integer
    67. '.........
    68. 'End Function
    69. End Class

    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „DTF“ ()

    kafffee schrieb:

    Jetzt war meine Frage, obs da sowas ähnliches wie ein ByRef gibt, wo ich in den Konstruktoren direkt Verweise auf die Properties in MeinService mitgeben kann, sodass meine ViewModel-Klassen das mitbekommen.


    Wie @DTF gesagt hat, ist ein Feature in neueren Versionen von .net, womit man sicher geht, dass keine Typen als null oder Nothing übergeben wird.
    Das ist ein Feature ähnlich wie Rust es hat; es hilft schon zu Compile-Zeit zu verhindern, dass du möglicherweise irgendwo einen Nullwert übergibst.

    Anders als @DTF, ist das für mich allerdings nicht nur für Anfänger gut, sondern ein ziemlich nützliches Feature, auch wenn es anfangs etwas nervig ist.
    Null-Dereferenzierung kann immer passieren und für merkwürdiges Verhalten oder gar ganz kaputte Software sorgen.

    kafffee schrieb:

    Was hat das mit den Fragezeichen auf sich, z.B. As Object??


    Egal für welche Variante du dich entscheidest, es erleichtert dir dadurch die Arbeit, dass du es auch für die Zukunft erweiterbar machst und nicht für jeden weiteren Wert einen weiteren Parameter übergeben musst.

    kafffee schrieb:

    Es kommt mir nicht in den Sinn wir mir das die Arbeit erleichtern soll...


    Genau das habe ich dir in meinem Beispiel gezeigt :)
    Class1 übergibt Class2 eine Referenz von sich selbst und Class2 abonniert daraufhin das MyEvent in Class1.

    Vielleicht hilft dir eine Erklärung von dem Unterschied zwischen Referenz- und Value-Typen:

    Spoiler anzeigen

    In .net (also C# und VB, wie genau die Semantik bei Microsoft's C++-Variante ist weiß ich nicht.) gibt es erstmal zwei Arten von Objekten:

    Strukturen
    struct oder Structure: das sind Value-Typen.
    Wenn du ein Value-Typ als Parameter übergibst, übergibst du immer eine Kopie des Wertes.

    Spoiler anzeigen

    C#-Quellcode

    1. // string ist ein struct!
    2. public void ChangeValue(int val) {
    3. val = 1337;
    4. }
    5. // hier wird explizit eine Reference auf den String im Speicher übergeben
    6. public void ChangeRefValue(ref int val) {
    7. value = 42;
    8. }
    9. public void Foo() {
    10. int = 0; // Speicher wird auf dem [b]Stack[/b] angelegt und zugewiesen
    11. ChangeValue(test);
    12. Console.WriteLine(test); // Output: "0"
    13. ChangeRefValue(ref test);
    14. Console.WriteLine(test); // Output: "42"
    15. }



    In dem Beispiel wird einmal der Wert als Kopie und als Referenz übergeben. In VB vergleichbar mit ByVal und ByRef.

    Klassen

    class, Class und Module sind Referenz-Typen.

    Hier ändert sich die Semantic etwas. Auch hier kann man als Kopie oder als Referenz übergeben.
    Hier muss man aber zu Value-Typen unterscheiden; hier wird nicht der Wert übergeben, sondern die Referenz.
    Referenzen sind fast wie Pointer, sie zeigen nur auf den Bereich im Speicher.

    Übergibst du ein Referenz-Typ ByValue, wird eine - und das ist nun wichtig - eine Kopie der Referenz übergeben. Diese Kopie der Referenz zeigt allerdings auf denselben Speicher!
    Übergibst du ein Referenz-Typ ByRef, wird aber die ursprüngliche Referenz auf den Wert übergeben. Man spart sich die Kopie.

    Spoiler anzeigen

    C#-Quellcode

    1. class TestClass { public int Test { get; set; } }
    2. public void ChangeValue(TestClass test) {
    3. test.Test = 1337;
    4. }
    5. public void ChangeRefValue(ref TestClass test) {
    6. test.Test = 42;
    7. }
    8. public void Foo() {
    9. TestClass test = new TestClass(); // Speicher wird auf dem [b]Heap[/b] angelegt und zugewiesen
    10. test.Test = 10;
    11. Console.WriteLine(test.Test); // Output: "10"
    12. ChangeValue(test);
    13. Console.WriteLine(test.Test); // Output: "1337"
    14. ChangeRefValue(ref test);
    15. Console.WriteLine(test.Test); // Output: "42"
    16. }



    Mehr Informationen, speziell für VB findest du hier: learn.microsoft.com/en-us/dotn…types-and-reference-types.


    Das sind die gleichen Mechanismen, die das .Net-Framework auch im Hintergrund verwendet, zum Beispiel fürs DataBinding.
    Klar, wenn man sich noch nicht damit auseinandergesetzt hat, dann ist es erstmal schwer den Kopf drum zu kriegen.

    Achtung: absolut subjektive Meinung!
    Das Problem hatte ich vor ewigen Monden auch mal mit VB, weil die Syntax in meinen Augen bei komplexeren Aufgaben alles schwerer zu verstehen macht. Die ganzen Konzepte hinter .Net, Objektorientierung usw. haben für mich erst in Java/C# Sinn ergeben.
    Vielleicht verstehst du es besser, wenn du es in C# durchführst?
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems
    Meine Privatwebseite: SimonC.eu

    Bitte nicht wundern, wenn meine Aktivitäten im Forum etwas langsamer sind, ich baue gerade mein Nebengewerbe zum Vollgewerbe aus.
    Ich versuche auf euch zurückzukommen :)
    @DTF

    Hast den Nagel auf den Kopf getroffen in der Rubrik "Wie schreibt man Code den auch kafffee versteht" :thumbsup:

    Genauso brauch ich meine Benamungen, auf deutsch, da weiss ich dann immer sofort "Aha, das hab ich fabriziert..." und ist kein Schlüsselwort...

    Okay, mal im Ernst:

    "Invoke" heisst ja auf deutsch so viel wie aufrufen, ich kenne diese Anweisung bis jetzt nur vom Thema "Threading" her, oder "Faden", wie @siycah sagen würde... Spass beiseite.

    Im Endeffekt ist also TellMeWhenLikeWithAnEvent nix anderes als ein Event, wenn man so will, und Invoke würde dann dem RaiseEvent entsprechen. Soweit richtig?
    Man könnte es wie ein Event sehen, da ist eine gewisse Parallele. Und "jain", es kommt aber nahe an RaiseEvent dran, denn damit wird wie du erkannt hast ausgelöst, nur kann ich grad nicht sagen ob RaiseEvent Invoke oder BeginInvoke näher kommt. Noch ein Detail dazu, Invoke wird sofort ausgeführt egal ob vorher noch andere Sachen im UI-Thread dran wären, das kommt vordrängeln in einer Warteschlange gleich. BeginInvoke wäre sich an eine Warteschlange anstellen an warten bis man dran ist. Aber bleib hier erstmal beim Invoke, sonst wird es komplizierter.

    Aber hört sich soweit gut an, hört sich an als wäre der Groschen gefallen.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DTF“ ()

    @DTF

    Ok nächster Schritt:

    Ich hab ja meine Properties mit den StreamHandles:

    VB.NET-Quellcode

    1. Private _streamfx0 As Integer
    2. Public Property streamfx0 As Integer
    3. Get
    4. Return _streamfx0
    5. End Get
    6. Set (value As Integer)
    7. _streamfx0 = value
    8. DelegateSubFürFertig.Invoke(0) 'hier würde ich das reinpacken, die 0 stünde quasi für streamfx0
    9. End Set
    10. End Property
    11. Private _streamfx1 As Integer
    12. Public Property streamfx1 As Integer
    13. Get
    14. Return _streamfx1
    15. End Get
    16. Set (value As Integer)
    17. _streamfx1 = value
    18. DelegateSubFürFertig.Invoke(1) 'hier würde ich das reinpacken, die 1 stünde quasi für streamfx1
    19. End Set
    20. End Property


    Uns ums mal praxisnah zu behalten (bitte sag mir wenn ich da auf dem Holzweg bin, aber um das zu verstehen, muss ich wissen auf was das hinausläuft). Das andere lass ich jetzt mal weg, das verwirrt mich noch ein bisschen:

    VB.NET-Quellcode

    1. New TellMeWhenLikeWithAnEvent(AddressOf HoleStreamHandle)


    VB.NET-Quellcode

    1. Public Function HoleStreamHandle(WelcheSpur As Integer) As Integer
    2. Select Case WelcheSpur
    3. Case 0
    4. Return streamfx0
    5. Case 1
    6. Return streamfx1
    7. End Select
    8. End Function

    kafffee schrieb:

    Genauso brauch ich meine Benamungen, auf deutsch

    Uiiii, ne da wäre ich raus :D
    Programmiersprachen sind auf Englisch, da macht es in meinen Augen viel mehr Sinn, dass das Selbstfabrizierte ebenfalls in derselben Sprache ist.
    Macht's auch für alle anderen verständlicher.

    Aber ist doch schön, dass du es verstanden hast! Wenn auch vielleicht nicht durch meine Weisheiten :D
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems
    Meine Privatwebseite: SimonC.eu

    Bitte nicht wundern, wenn meine Aktivitäten im Forum etwas langsamer sind, ich baue gerade mein Nebengewerbe zum Vollgewerbe aus.
    Ich versuche auf euch zurückzukommen :)

    kafffee schrieb:

    Uns ums mal praxisnah zu behalten

    Auf dem ersten Blick könnte das OK sein, ich habe aber zu wenig Kontext. Vermute aber das geht gut los. Probiere einfach das zu implmentieren, ich denke das kannst du jetzt :thumbup:

    siycah schrieb:

    Uiiii, ne da wäre ich raus

    Ich habe mal in einer Firma angefangen, alles schien zu schön um war zu sein, gute Atmosphäre, nette Kollegen, gutes Gehalt, freie Zeiteinteilung.....
    Am ersten Arbeitstag sollte ich einen bestehendes Programm um ein Feature erweitern, ich hab fast einen Herzkasper bekommen als ich "Denglish" sah. Was keine Sau erwähnte, das der Chef das auf deutsch will. Direkt am ersten Tag neuen Job gesucht, war keine 2 Wochen in der Firma, zum Glück gibt es Probezeiten :D

    Edit:
    @kafffee
    Mach besser so, falls die delegaten noch null sind, könnte dir eine NullReferenceException um die Ohren fliegen.

    VB.NET-Quellcode

    1. If Not DelegateFunktionMultiplikation Is Nothing Then
    2. 'invoken
    3. End If


    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „DTF“ ()

    DTF schrieb:

    Was keine Sau erwähnte, das der Chef das auf deutsch will. Direkt am ersten Tag neuen Job gesucht, war keine 2 Wochen in der Firma, zum Glück gibt es Probezeiten


    Uff, ja da gehe ich 100% mit. Als ich bei mir angefangen habe, habe ich die komplette Software umgestrickt und mit den neu dazugekommen Kollegen Vereinbarungen getroffen, dass alles auf englisch gehalten wird.
    Mal abgesehen von der Tatsache, dass ich Muttersprachler bin, ist die gesamte IT-Welt sowieso englisch, da macht es nur Sinn, den Quellcode auch auf Englisch zu halten.
    Steht (zum Glück) auch in allen offiziellen Guidelines.
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems
    Meine Privatwebseite: SimonC.eu

    Bitte nicht wundern, wenn meine Aktivitäten im Forum etwas langsamer sind, ich baue gerade mein Nebengewerbe zum Vollgewerbe aus.
    Ich versuche auf euch zurückzukommen :)