Entwickler-Ecke

Basistechnologien - Rest einer enum Addition ermitteln


Delete - Fr 16.06.17 15:24
Titel: Rest einer enum Addition ermitteln
- Nachträglich durch die Entwickler-Ecke gelöscht -


C# - Fr 16.06.17 15:34

Hey,

das sollte dein Problem lösen:


C#-Quelltext
1:
2:
var bsp = Beispiel.C | Beispiel.B;
var notIncluded = Enum.GetValues(typeof(Beispiel)).Cast<Beispiel>().Where(b => (b & bsp) == 0)


Delete - Fr 16.06.17 15:48

- Nachträglich durch die Entwickler-Ecke gelöscht -


Palladin007 - Fr 16.06.17 22:05

Darf ich fragen, was das bringt?

Das sieht für mich sehr nach einem Anwendungsbeispiel vom FlagsAttribute [https://www.dotnetperls.com/enum-flags] aus


Delete - Fr 16.06.17 22:54

- Nachträglich durch die Entwickler-Ecke gelöscht -


C# - Fr 16.06.17 23:39

Naja zu kannst ja zwischen enum und int casten:

C#-Quelltext
1:
Enum.GetValues(typeof(Beispiel)).Cast<int>().Where(b => (b & (int)bsp) == 0)                    


Du kannst das Ganze natürlich auch ohne Linq machen. Ich wüsste nur nicht warum. Zumal du dann nicht um eine Schleife herum kommst. Irgendwie musst du ja alle Elemente des Enums abfragen.


Delete - Sa 17.06.17 00:13

- Nachträglich durch die Entwickler-Ecke gelöscht -


Ralf Jansen - Sa 17.06.17 13:13

C# Enums sind maximal ein ähnliches Konzept zu Delphi Sets da sollte man vorsichtig sein das eine mit dem anderen nachzustellen.

Ein Enum ist keine Aufzählung aller gültigen Werte dieses Enums. Eine Enum ist eine Aufzählung aller benannten Werte des Basistypen. Es sind aber alle Werte des Basistypen erlaubt auch die nicht benannten. Insofern würde ich wenn ich eine solche Fragestellung hätte wie deine am Enum erstmal explizit definieren was denn erlaubt sein soll (ein All Eintrag im enum). Das gibt dann, denke ich einen halbwegs lesbaren Syntax auch wenn man mit einem Mengen-Mindset an die Sache geht ;)


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
[Flags]
enum Beispiel
{
    None = 0,
    A = 1
    B = 2
    C = 4
    D = 8,
    All = A | B | C | D
}

var bsp = Beispiel.C | Beispiel.B;
var notIncluded = Beispiel.All & ~bsp;


Richtig lesbar wird es dann wenn man passende Extension Methods einsetzt auch wenn enums nur ein mäßig gutes Ziel dafür sind.


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
var bsp = Beispiel.C | Beispiel.B;
var notIncluded2 = Beispiel.All.Without(bsp);

public static class EnumExtensions
{
    public static T Without<T>(this Enum value, T without) where T : struct, IComparable, IFormattable, IConvertible  // genauest mögliche Enum Einschränkung
    {
        if (!typeof(T).IsEnum)
            throw new ArgumentException($"{nameof(T)} is not an enum type.");
        if (!(value is T))
            throw new ArgumentException($"{nameof(value)} is not of type {nameof(T)}");

        return (T)ConvertToUnderlyingType(typeof(T), Convert.ToInt64(value) & ~Convert.ToInt64(without));
    }

    private static object ConvertToUnderlyingType(Type enumType, long value)
    {
        // Drecks Typesystem!!
        switch (Type.GetTypeCode(enumType.GetEnumUnderlyingType()))
        {
            case TypeCode.Byte:
                return Convert.ToByte(value);
            case TypeCode.SByte:
                return Convert.ToSByte(value);
            case TypeCode.UInt16:
                return Convert.ToUInt16(value);
            case TypeCode.Int16:
                return Convert.ToInt16(value);
            case TypeCode.UInt32:
                return Convert.ToUInt32(value);
            case TypeCode.Int32:
                return Convert.ToInt32(value);
            case TypeCode.UInt64:
                return Convert.ToUInt64(value);
            case TypeCode.Int64:
                return Convert.ToInt64(value);
            case TypeCode.Object:
            default:
                throw new InvalidOperationException($"Unknown underlying type of enum {enumType.FullName}");
        }
    }
}



PS. Da gerade das Highlighting im Forum ein Thema war. Der cs Highlighter kennt Interpolated Strings noch nicht.


Delete - Sa 17.06.17 14:47

- Nachträglich durch die Entwickler-Ecke gelöscht -


Christian S. - Sa 17.06.17 14:58

== Off-Topic Start ==

user profile iconRalf Jansen hat folgendes geschrieben Zum zitierten Posting springen:
PS. Da gerade das Highlighting im Forum ein Thema war. Der cs Highlighter kennt Interpolated Strings noch nicht.

Das ist auch ziemlich fies. Aber lokal scheint es zu gehen, wenn ich C# als Inline-Sprache von C# einbinde :nut:

== Off-Topic Ende ==


Ralf Jansen - Mo 19.06.17 11:03

Kleine Anmerkung. Jetzt wo ich das nochmal gesehen habe ist die Verwendung des (^) XOR Operators eher falsch. Es sollte besser das klassische &~ sein. Ich zieh mal den Code nach.


Delete - Mo 19.06.17 11:57

- Nachträglich durch die Entwickler-Ecke gelöscht -


C# - Mo 19.06.17 14:33

Gibts da ne konkrete Frage dazu?


Delete - Mo 19.06.17 19:31

- Nachträglich durch die Entwickler-Ecke gelöscht -