<Flags> Enum

  • VB.NET

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von Niko Ortner.

    <Flags> Enum

    Hallo zusammen,
    ich habe mich mal an Flags probiert.
    Ich möchte dem Programmierer die Möglichkeit geben mehrere Flags zu setzen.
    Dazu habe ich Folgenden <Flag()> Enum gebaut

    VB.NET-Quellcode

    1. <Flags()> Enum OverWrite
    2. Never = 0
    3. EveryTime = 1
    4. TargetIsOlder = 2
    5. SourceIsBigger = 4
    6. End Enum

    Ein Aufrufbeispiel () ' welches Funktioniert.

    VB.NET-Quellcode

    1. ' Copy File
    2. Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
    3. DoWork = New LocalFileSystemService
    4. ' Achtung Flags() werden mit "Or" verknüpft nicht mit "And"
    5. If DoWork.FileCopy(Uri_Lokal_Alice, Uri_Lokal_Target, OverWrite.EveryTime Or OverWrite.TargetIsOlder) = True Then
    6. MessageBox.Show("Kopiert")
    7. Else
    8. MessageBox.Show("nicht Kopiert")
    9. End If
    10. End Sub

    Die verkürzte Auswertung

    VB.NET-Quellcode

    1. ElseIf OverWriteAction = (OverWrite.EveryTime Or OverWrite.TargetIsOlder) Then
    2. MessageBox.Show("Every Time and Older" & vbNewLine & OverWriteAction.ToString)
    3. ' Check Date
    4. ' Wenn das TargetDatum (CreationTime) kleiner als das SourceDatum ist dann Kopieren
    5. If Date_Is_Lower(FITargetDate, FISourceDate) Then
    6. ' Das Target Datum war kleiner also Kopieren
    7. FileCopyNow = New Functions
    8. If FileCopyNow.CopyFile(uri, targeturi) = True Then
    9. ' Alles OK ich habe Kopiert
    10. Return True
    11. Else
    12. ' Fehler aufgetreten ich habe nicht Kopiert
    13. Return False
    14. End If
    15. Else
    16. ' Das Target Datum war größer also nicht Kopieren
    17. Return False
    18. End If

    So bis hier geht denn man alles.

    Mein Problem wo ich nicht hinter steige ist, wenn der Programmierer ein Flag zuviel angibt läuft er trotzdem dort hin.
    Durch das hinzufügen eines Zusätzlichen Flags Provoziere ich absichtlich einen Fehler.
    Der Fehler Aufruf der trotzdem funktioniert.

    VB.NET-Quellcode

    1. ' Der Flag der zuviel ist => OverWrite.Never
    2. If DoWork.FileCopy(Uri_Lokal_Alice, Uri_Lokal_Target, OverWrite.Never Or OverWrite.EveryTime Or OverWrite.TargetIsOlder) = True Then


    Was übersehe ich hier oder was verstehe ich Falsch ?

    lieben dank

    Bernd
    Hi
    in dem Fall brauchst du keine Flags, da EveryTime Or TargetIsOlder eh auf EveryTime rauslaufen müsste. Wenn du Never Or EveryTime Or TargetIsOlder benutzt, fällt Never automatisch weg, da 0 Or X immer X ergibt. Wenns noch ncht klar ist: Bei 0 sind alle Bits 0. Bei Or ist die Rechenregel einfach, dass falls mindestens eines der beiden verglichenen Bits 1 ist, das Ergebnis ebenfalls 1 ist:
    a b | a Or b
    0 1 | 1
    1 0 | 1
    1 1 | 1
    0 0 | 0

    Da bei 0 eben jedes Bit auf 0 ist und bei allen anderen Werten eben nicht, werden die Bits des anderen einfach übernommen. ==> 0 Or X = X.

    In deinem Fall sind die Flags aber wie gesagt überflüssig.

    Gruß
    ~blaze~
    Hallo ~blaze~
    wie immer schnell und zuverlässig.
    Da wollte ich dich nicht per PN belästigen und du bist doch schon wieder da. Cool, danke.

    Das mit dem Never und EveryTime war jetzt das blödeste Beispiel welches ich hier vorgeben konnte. Sorry :love:
    Natürlich verbirgt sich hinter der Methode noch viel mehr, daher die Eingekürzte Variante und auch nur als Beispiel.

    Ok klar wenn bei Or einer 1 ist leuchtet ein.

    Es gibt aber noch viel mehr Varaiationen, von denen ich nur die richtigen durchlassen möchte.

    Wie stellte ich das denn am Übersichtlichsten dar ?

    Nicht einfach, nur Übersichtlich.

    lieben dank

    Bernd
    Du kannst ja in Deine Flags "verbotene Kombinationen" aufnehmen:

    VB.NET-Quellcode

    1. OlderBigger = TargetIsOlder Or SourceIsBigger
    2. 'und dann abtesten:
    3. If (inputFlag And OlderBigger) = OlderBigger Then
    4. MessageBox.Show("Verboten")
    5. Return
    6. End If
    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!
    @Rod

    ebenfalls vielen dank.

    Kann mir mal einer etwas Hirnwasser reichen.
    Manchmal .......

    Jetzt hat es Klick gemacht.

    danke

    Nur dann habe ich aber ein anderes Problem,
    somit muss ich vorab alle Fehleingaben ermitteln.
    Also alle Falscheingaben die Möglich sind ermitteln und auch abfangen.
    Das ist ne Menge Arbeit und vorallem darf ich keine vergessen.

    Einfacher wäre dann ne Select Case
    wobei das mit Flags nicht Möglich ist. Soweit ich Informiert bin.

    Gibt es noch andere Ideen ? bevor ich mich auf der Suche nach allen Variationen mache ?

    lieben dank

    Bernd
    Oder halt im Code mit Select Case und (Value And (EnumValue1 Or EnumValue2)) = (EnumValue1 Or EnumValue2).
    Oder mit einer separaten Routine, die vorgegebene Möglichkeiten als solche und auf Gut und Schlecht testet, der Möglichkeiten gibt es da viele.
    Da musst Du halt Deinen Stil entwickeln.
    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!
    Warum nimmst du eigentlich das Flags Attribut, wenn du eh' nicht HasFlag verwendest?

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    3. Dim f As Foo = Foo.IsCool Or Foo.HasStyle
    4. If f.HasFlag(Foo.HasStyle) AndAlso f.HasFlag(Foo.IsCool) Then
    5. MessageBox.Show("Cool and Stylish!")
    6. End If
    7. If f.HasFlag(Foo.CombinedStyleCool) Then
    8. MessageBox.Show("Also cool and stylish!")
    9. End If
    10. End Sub
    11. End Class
    12. <Flags()> Public Enum Foo
    13. IsCool = 1
    14. IsHot = 2
    15. HasStyle = 4
    16. CombinedStyleCool = IsCool Or HasStyle
    17. End Enum

    Bernd schrieb:

    Mein Problem wo ich nicht hinter steige ist, wenn der Programmierer ein Flag zuviel angibt läuft er trotzdem dort hin.
    Durch das hinzufügen eines Zusätzlichen Flags Provoziere ich absichtlich einen Fehler.
    Der Fehler Aufruf der trotzdem funktioniert.

    VB.NET-Quellcode

    1. ' Der Flag der zuviel ist => OverWrite.Never
    2. If DoWork.FileCopy(Uri_Lokal_Alice, Uri_Lokal_Target, OverWrite.Never Or OverWrite.EveryTime Or OverWrite.TargetIsOlder) = True Then
    Was übersehe ich hier oder was verstehe ich Falsch ?
    Naja das geht natürlich nicht. OverWrite.Never hast du ja auf 0 festgelegt, das hat beim ver-odern natürlich keinerlei Auswirkung.
    So ich habe mir das nochmal in ruhe angeschaut.
    @Rod das mit den Verbotenen Flags geht sehr schön. Jedoch ist es bei der Menge Verbotener Kombinationen einfacher die nicht Verbotenen abzufragen. Da es zu viele sind macht der Einsatz von Flags keinen sinn mehr.

    @Pico deine Variante ist eigentlich am schönsten. Jedoch habe ich das FW auf 2.0 runter geschraubt.
    Ich möchte die entstehende DLL auch in alten Projekten verwenden.


    Ich werde also nach einem anderen Weg suchen.

    ~blaze~ schrieb:

    In deinem Fall sind die Flags aber wie gesagt überflüssig.

    Wie meinst du das genau ? Welchen Ansatz hat du damit gemeint ?


    vielen dank
    Bernd
    Dann bau Dir doch eine eigene Funktion HasFlags().
    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!
    Sorry, war Quatsch, da war die Überlegung falsch.
    Allerdings kannst du das auch so machen:

    VB.NET-Quellcode

    1. <Flags()> Public Enum OverwriteMode
    2. Never = 0
    3. TargetIsOlder = 1
    4. SourceIsBigger = 2
    5. Everytime = -1
    6. End Enum


    Damit beinhaltet Everytime auch TargetIsOlder und SourceIsBigger und andererseits Everytime And Not TargetIsOlder eben nur SourceIsBigger und andere. Bei -1 sind alle Bits auf 1.

    Gruß
    ~blaze~
    So ich habe das jetzt etwas anders gelöst.
    Ich frage nur noch die ab die zulässig sind.
    Enums sind nun keine <Flags()> Enum sondern einfache Enums.

    VB.NET-Quellcode

    1. Public Enum CopyFlags
    2. Never = 1
    3. EveryTime = 2
    4. TargetIsOlder = 4
    5. SourceIsBigger = 8
    6. End Enum

    Bei der Ankunft bekomme ich nun eine Summe der gesetzten Flags. (sind zwar keine Flags)
    Nun fange ich gleich ab ob "Never" vorhanden ist.

    VB.NET-Quellcode

    1. Dim FlagsValue As Integer = CInt(OverWriteAction)
    2. ' Wenn "Never" vorhanden dann sofort raus. Nur Rest 0 lässt durch. Also gerade Zahlen.
    3. If FlagsValue Mod 2 = 1 Then
    4. MessageBox.Show("Rest 1. Never is in it. Cancel.")
    5. Return False
    6. Exit Function
    7. End If

    Dann bleiben nur noch 4 weitere Möglichkeiten übrig.

    VB.NET-Quellcode

    1. ' Prüfen auf 2, 4, 6, 8, 10, 12, 14
    2. If FlagsValue = 4 Then
    3. MessageBox.Show("Only TargetIsOlder.")
    4. ' read file info
    5. ' call copy function
    6. Return True
    7. End If
    8. If FlagsValue = 8 Then
    9. MessageBox.Show("Only SourceIsBigger")
    10. ' read file info
    11. ' call copy function
    12. Return True
    13. End If
    14. If FlagsValue = 12 Then
    15. MessageBox.Show("TargetIsOlder and SourceIsBigger")
    16. ' read fileinfos
    17. ' call copy function
    18. Return True
    19. End If
    20. Select Case FlagsValue
    21. Case 2, 6, 10, 14
    22. MessageBox.Show("EveryTime is in it. So copy without more questions.")
    23. ' call copy function without read fileinfos
    24. Return True
    25. End Select

    Ohne Beachtung der Reihenfolge. Die werde ich mir jetzt noch genauer ansehen.
    Aus die Maus. Das war es auch schon.

    Antwort ist nur für die Nachwelt und damit in Google nicht ständig solche unbrauchbaren Ergebnisse angezeigt werden.


    Nochmals danke an alle die so toll geantwortet haben. Ich habe alle Antworten ausprobiert.

    Bernd

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

    Ist zwar erledigt, aber ich finde, das sollte noch dazu:
    Ich würde Dir raten Werte so abzufragen:

    VB.NET-Quellcode

    1. If (Value And CopyFlags.Never) = CopyFlags.Never Then


    Das hat den Vorteil, dass man bei Änderungen nicht im ganzen Code nach Zahlen suchen muss.

    Nächstes: Das extra Always-Flag ist unnötig. Wenn man keine Bedingung angibt, die eingehalten werden muss (None = 0), dann muss keine Bedingung eingehalten werden, was bedeutet, dass es immer passt, und es wird immer überschrieben.

    Dann würde ich das direkt in die Copy Methode einbauen, mit einer eigenen HasFlag() Funktion:

    VB.NET-Quellcode

    1. Enum CopyFlags As Integer 'Das "As Integer" habe ich mir angewöhnt
    2. None = 0 'Könnte auch "Always = 0" heißen
    3. Never = 1
    4. TargetIsOlder = 2
    5. SourceIsBigger = 4
    6. End Enum
    7. Function HasFlag(ByVal Flags As CopyFlags, SearchFlag As CopyFlags) As Boolean
    8. Return (Flags And SearchFlag ) = SearchFlag
    9. End Function
    10. Sub Copy(ByVal Flags As CopyFlags)
    11. Dim AlteDatei As DateiDingens
    12. Dim NeueDatei As DateiDingens
    13. If Not HasFlag(Flags, CopyFlags.Never) AndAlso _
    14. (AlteDatei.Datum < NeueDatei.Datum OrElse Not HasFlag(Flags, CopyFlags.TargetIsOlder)) AndAlso _
    15. (AlteDatei.Größe < NeueDatei.Größe OrElse Not HasFlag(Flags, CopyFlags.SourceIsBigger)) Then
    16. 'Alte Datei überschreiben
    17. End If
    18. End Sub


    Hier wird abgefragt:
    1. Wenn das Never-Flag gesetzt ist wird sowieso übersprungen, da die Gesamtbedingung nicht mehr True sein kann.
    2. Alle Teilbedingung werden nach dem selben Prinzip abgehanelt:
    Alle Teilbedingung müssen True sein, damit die Datei kopiert wird.
    Wenn eine Abfrage einer Teilbedingung (Links vom OrElse) True ist, dann ist die Teilbedingung auf jeden Fall True (Unabhängig davon, ob sie ignoriert wird oder nicht).
    Wenn eine Abfrage False ist, dann wird entschieden, ob sie nötig war. Wenn sie nicht nötig war (also das Flag nicht gesetzt war (Rechts vom OrElse)), dann wird immer noch True zurückgegeben. Wenn sie nötig war, dann wird False zurückgegeben.
    3 Wenn alle Teilbedingungen True sind, dann wird kopiert.

    So lassen sich auch noch andere Bedingungen einfügen:

    VB.NET-Quellcode

    1. Enum CopyFlags As Integer 'Das "As Integer" habe ich mir angewöhnt
    2. None = 0 'Könnte auch "Always = 0" heißen
    3. Never = 1
    4. TargetIsOlder = 2
    5. SourceIsBigger = 4
    6. SomeCondition = 8
    7. End Enum
    8. '...
    9. If Not HasFlag(Flags, CopyFlags.Never) AndAlso _
    10. (AlteDatei.Datum < NeueDatei.Datum OrElse Not HasFlag(Flags, CopyFlags.TargetIsOlder)) AndAlso _
    11. (AlteDatei.Größe < NeueDatei.Größe OrElse Not HasFlag(Flags, CopyFlags.SourceIsBigger)) AndAlso _
    12. (SomeCondition(AlteDatei, NeueDatei) OrElse Not HasFlag(Flags, CopyFlags.SomeCondition)) Then


    So sollte das eigentlich recht simpel sein.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils