Structure per Index ansprechen

  • VB.NET
  • .NET 7–8

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Structure per Index ansprechen

    Hallo,
    ich habe mal eine Anfängerfrage :/ In meinem Code benutze ich Strukturen, um Variablen der besseren Lesbarkeit halber zu sortieren :

    VB.NET-Quellcode

    1. Structure Struct_Betriebsart
    2. Public Anlage_Ein As Boolean
    3. Public Anlage_Aus As Boolean
    4. Public Handbetrieb As Boolean
    5. Public Automatik As Boolean
    6. Public Auto_Start As Boolean
    7. Public Auto_Stop As Boolean
    8. Public Softstop As Boolean
    9. Public Reset As Boolean
    10. End Structure
    11. Public Betriebsart As Struct_Betriebsart


    Die einzelnen Variablen beschreibe ich dann irgendwo innerhalb des Programms z.B. so :

    VB.NET-Quellcode

    1. Betriebsart.Handbetrieb = True


    Soweit, so gut. Nun möchte ich aber am Ende nicht jede Variable wieder einzeln auslesen (z.B. um die Werte an einen Roboter, eine SPS etc. zu senden), sondern das ganze automatisiert in einer For...Next Schleife machen, also in etwa so :

    VB.NET-Quellcode

    1. For index = 0 to Betriebsart.count-1
    2. Send(Betriebsart(index))
    3. Next


    Ist so natürlich Quatsch, aber geht sowas irgendwie dass man Variablen einerseits über den Namen (wegen der besseren Lesbarkeit) und andererseits auch über einen Index anspricht ?
    Mir fällt da z.B. eine List(Of... ein

    VB.NET-Quellcode

    1. Private betriebsartenListe As New List(Of Struct_Betriebsart)()
    2. betriebsartenListe.Add(New Struct_Betriebsart With {
    3. .Anlage_Ein = True,
    4. .Anlage_Aus = False,
    5. })


    Oder vielleicht auch über ENUMs?
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Willkommen im Forum.

    Klar geht das:

    VB.NET-Quellcode

    1. Structure Struct_Betriebsart
    2. Public Anlage_Ein As Boolean
    3. Public Anlage_Aus As Boolean
    4. Public Handbetrieb As Boolean
    5. Public Automatik As Boolean
    6. Public Auto_Start As Boolean
    7. Public Auto_Stop As Boolean
    8. Public Softstop As Boolean
    9. Public Reset As Boolean
    10. Function GetAllValues() As Ienumerable(Of Boolean)
    11. Return {Anlage_Ein, Anlage_Aus, Handbetrieb, Automatik, Auto_Start, Auto_Stop, Softstop, Reset}
    12. End Function
    13. End Structure
    14. '…
    15. For index = 0 to Betriebsart.GetAllValues.Count - 1
    16. Send(Betriebsart.GetAllValues(index))
    17. Next
    18. 'oder besser
    19. For Each Value In Betriebsart.GetAllValues
    20. Send(Value)
    21. Next


    Aber kann es sein, dass sich manche Werte inhaltlich ausschließen? Können denn z.B. Anlage_Ein und Anlage_Aus gleichzeitig den gleichen Wert haben, also z.B. beide auf True stehen, und trotzdem ergibt es Sinn?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @guido-b Ebenfalls Willkommen im Forum. :thumbup:
    Statt der Structure kannst Du auch ein Boolean-Array verwenden, da hast Du automatisch die Indizes.
    Wenn Du dazu Namen benötigst, kannst Du die in einem String-Array ablegen
    oder
    Du machst Die ein Dictionary(Of String, Boolean), da kannst Du die Werte mit dem Namen auslesen.
    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!
    Erstmal vielen Dank für die Vorschläge !

    Aber kann es sein, dass sich manche Werte inhaltlich ausschließen? Können denn z.B. Anlage_Ein und Anlage_Aus gleichzeitig den gleichen Wert haben, also z.B. beide auf True stehen, und trotzdem ergibt es Sinn?


    Die Namen sind nur zufällige Beispiele, die ich aus einem aktuellen Projekt kopiert habe, bitte nicht an den Begriffen stören. In diesem Fall gibt es auf der Form jeweils einen Button für Anlage_Ein und Anlage_Aus, die 1:1 an die SPS durchgereicht werden, daher macht es hier Sinn. Aber wie gesagt, ich hätte das auch Variable_00 bis Variable_07 nennen können.

    Was mir noch nicht so gut gefällt ist die Tatsache, dass ich bei einem Dictionary keine Hilfe/Vorschläge beim Programmieren bekomme wie bei einem Struct. Wenn ich bei letzterem z.B. Betriebsart. eingebe, bekomme ich eine Liste mit allen Variablen innerhalb dieser Struktur angezeigt und kann mir die passende aussuchen. Das ist sehr hilfreich wenn man eine große Zahl an Variablen verwaltet oder mehrere Personen an einem Projekt arbeiten, deshalb habe ich die ja strukturiert (Thema Lesbarkeit). Bei einem Dictionary muss ich schon genau wissen wie die Variable heißt, um sie mit

    VB.NET-Quellcode

    1. Betriebsart.​Item("Anlage_Ein") = True
    beschreiben zu können

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „guido-b“ ()

    @guido-b Im Sinne einer c++-union kannst Du Dir ein Äquivalent basteln und so Deinen Zugriff organisieren.
    stackoverflow.com/questions/126781/c-union-in-c-sharp
    aspheute.com/artikel/20020207.htm
    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!
    Du könntest auch Reflection verwenden:

    VB.NET-Quellcode

    1. Public Shared Sub PrintStates()
    2. Dim wt = New MyStruct() With {
    3. .Value1 = True,
    4. .Value2 = False,
    5. .Value3 = Nothing
    6. }
    7. Dim fi As FieldInfo() = GetType(MyStruct).GetFields()
    8. For Each info In fi
    9. Console.WriteLine($"{info.Name}: {info.GetValue(wt)}")
    10. Next
    11. End Sub


    Ist allerdings etwas langsamer als ein Dictionary.
    wurde bereits in post#2 gesagt: Enum ist dein Froind.

    MIt Bit-Operationen kann man da auch in einer Schleife die gesetzten Bits draus extrahieren.

    Ich empfehle sehr das kostenlose vb.net-Buch von Löffelmann. zumindest in der Auflage von 2005 ist da ein ganz fabelhaftes Kapitel über Enums drinne.
    Weil es ist schon ziemlich mächtig, was man mit Enums zuwege bringen kann, und die laufen dir auch sonst auf schritt und tritt übern weg.

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

    Sorry, irgendwie habe ich mich wohl falsch ausgedrückt. Ich habe eure obigen Beispiele mal ausprobiert, aber keins davon geht in die richtige Richtung. Liegt wohl daran dass ich eigentlich aus der SPS Programmierung komme und mit vb.net nur am Rande zu tun habe. Ich hatte gehofft eine Art Struktur/Klasse/Liste/wieauchimmer... zu finden, auf deren Inhalt ich sowohl per Name

    VB.NET-Quellcode

    1. Betriebsart.Anlage_Ein = True
    als auch per Index

    VB.NET-Quellcode

    1. Betriebsart.Item(0) = True
    zugreifen kann. Eigentlich dachte ich das wäre total simpel, aber vermutlich gibt es sowas schlicht und ergreifend nicht. Also nochmals vielen Dank für die Antworten.
    Also falls es soetwas nicht schon gibt lässt sich sowas recht leicht selbst bauen. Leider reichen meine VB Kenntnisse dafür nicht daher in c#.

    Ich hab "per Name" falsch verstanden.
    *Spoiler entfernt*

    Hier wäre mal sowas glaube ich:
    Spoiler anzeigen

    C#-Quellcode

    1. internal class GotNoName<T>
    2. {
    3. public T Value1 { get; set; }
    4. public T Value2 { get; set; }
    5. public T this[int index]
    6. {
    7. get
    8. {
    9. if (propertyInfos == null)
    10. return default;
    11. if (index < 0 || index >= propertyInfos.Length)
    12. throw new ArgumentOutOfRangeException("index");
    13. return (T)propertyInfos[index].GetValue(this);
    14. }
    15. set
    16. {
    17. if (propertyInfos == null)
    18. return;
    19. if (index < 0 || index >= propertyInfos.Length)
    20. throw new ArgumentOutOfRangeException("index");
    21. propertyInfos[index].SetValue(this, value);
    22. }
    23. }
    24. private readonly PropertyInfo[] propertyInfos;
    25. public GotNoName() => propertyInfos = GetType().GetProperties().Where(x => x.Name != "Item").ToArray();
    26. }


    C#-Quellcode

    1. var cls = new GotNoName<string>();
    2. cls.Value1 = "Hallo";
    3. cls[1] = "Welt";
    4. Console.WriteLine($"Value1: {cls.Value1}");
    5. Console.WriteLine($"Value2: {cls[1]}");
    6. Console.ReadLine();

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Fakiz“ ()

    wie gesagt, mit enum geht sowas.

    VB.NET-Quellcode

    1. Public Enum BetriebsArtEnm: A:B=A<<1:C=B<<1:D=C<<1:E=D<<1:End Enum
    2. dim BetriebsArt As BetriebsArtEnm = BetriebsArtEnm.A
    3. BetriebsArt = BetriebsArt OR BetriebsArtEnm.C
    4. dim n=3
    5. BetriebsArt = BetriebsArt OR (1 << n)
    Damit kann man im Enum das n-te Bit setzen.
    Ebensogut kann man die Enum-Member aber auch per Namen ansprechen.

    Aber wer nicht hören will - der muss es auch nicht.

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

    ErfinderDesRades schrieb:

    mit enum geht sowas.
    Fast. ;)

    VB.NET-Quellcode

    1. BetriebsArt = CType(BetriebsArt Or (1 << n), BetriebsArtEnm)

    =====
    Sinnigerweise kommt dabei der numerische Wert, nicht aber das Enum.ToString() bei raus, in C# genau so, da genügt

    C#-Quellcode

    1. enum BetriebsArtEnm
    2. {
    3. A = 0,
    4. B = 0,
    5. C = 0,
    6. D = 0,
    7. E = 0
    8. }

    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!

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