Flagged Enum Consolidation (Inverse of Combination) Using LINQ - c#

I am trying to generate an inverse of a flagged enumeration. Below is the enum:
[Flags]
public enum MyType
{
Unknown = 0,
A = 1 << 0,
B = 1 << 2,
C = 1 << 3,
D = 1 << 4,
E = 1 << 5,
F = 1 << 6
}
I have defined a static MyType mtGroup1 with a value of (A | B). I would like to generate the inverse of this, excluding Unknown.
My solution:
MyType t = MyType.Unknown;
foreach (var vType in Enum.GetValues(typeof(MyType)).OfType<MyType>())
{
if ((mtGroup1 & vType) != vType)
t = t | vType; //Consolidates into a single enum, excluding unknown
}
The resulting value of t is C | D | E | F, which is the desired outcome.
This method works, but I was hoping there was a more simple way to consolidate as shown above using LINQ (other, non-LINQ ways are also acceptable if simpler).
Thanks!

My Unconstrained Melody project makes this really simple:
MyType inverse = mtGroup1.UsedBitsInverse();
The project contains a number of useful methods (many written as extension methods) which use "unspeakable" generic constraints (ones which are understood by the C# compiler but can't be expressed in C#) to constrain generic type parameters to be enum types or delegates. In this way, the above code manages to work without any boxing - and it actually works out all the "interesting" bits of an enum type once, the first time that type is used in conjunction with Unconstrained Melody, so this operation is blindingly efficient.
If you don't want to use Unconstrained Melody, you could write your own method to find the "used bits" of an enum once, then just use:
MyType t = UsedBitsOfMyType & ~mtGroup1;

Related

Alternative to operand && (C#)

so I'm trying to make a code with &&. However, when I put that in, it said that I couldn't apply the operand to it.
In specific, it reads: Operator "&&" cannot be applied to operands of type 'Server.Enums.PokemonType' and 'Server.Enums.PokemonType'
However, I need to be able to link these two things so I can make the code be two PokemonTypes. So is there any alternative or work-around for not being able to use &&?
If you need it, this is my code:
case 225:
{
//Flying Press -- INCOMPLETE, needs Flying-type
setup.Move.Element = Enums.PokemonType.Fighting && setup.Move.Element = Enums.PokemonType.Flying;
if (setup.Defender.VolatileStatus.GetStatus("Minimize") != null)
{
setup.Multiplier *= 2;
setup.Move.Accuracy = -1;
}
}
break;
The system defined && operator only supports boolean operands. The & operator will work for enums (because it also works on all integer types, which the enums are based on). Of course, if you want an enum that represents the combination of two flag values then you'll want to OR them together (using |), not AND them together.
To add multiple values to a enum variable you need to declare the enum with [Flags] attribute.
So your enum would be:
[Flags]
public enum PokemonType
{
Fighting = 1 << 0,
Flying = 1 << 1,
Normal = 1 << 2,
Dragon = 1 << 3,
}
Define enumeration constants in powers of two, that is, 1, 2, 4, 8, and so on. This means the individual flags in combined enumeration constants do not overlap
Then assign using Enums.PokemonType.Fighting | Enums.PokemonType.Flying so it is possible to track all values assigned to it later.

operator overloading for primitive types

I am using a class as a wrapper to hold a group of several unsigned shorts that represent different options or characteristics. Each short is initialized to be a power of two so I can easily add or or them together.
public static class Options
{
public static readonly ushort OPTN0 = 1 << 0; // 0001
public static readonly ushort OPTN1 = 1 << 1; // 0010
public static readonly ushort OPTN2 = 1 << 2; // 0100
...
}
public static void main(string[] args)
{
funcThatUsesOptns(Option.OPTN0); // works fine
funcThatUsesOptns(Option.OPTN1 | Option.OPTN2); // fails because '|' returns int
funcThatUsesOptns((ushort)(Option.OPTN0 | Option.OPTN2)); // works fine
...
}
However, since "+" and "|" both return ints in this situation, I have to cast them every time I do. For example, both a and b are initialized as ints:
var a = Option.OPTN0 + Option.OPTN1;
var b = Option.OPTN0 | Option.OPTN1;
So I was wondering if operator overloading was possible for primitive types. If not, are there any better ways of achieving this? Of course it isn't going to kill me to just cast it every time, but I was hoping for a cleaner way.
Edit:
I am actually using this to render a lot of simple geometric objects (cubes, pyramids,...). I would like to be able to quickly tell the renderer which faces to draw. If a face on one object is touching another or is facing away from the camera, I can set the corresponding bit to tell the renderer not to draw that face.
It seems like what you really want here are enum values based on ushort, like this:
[Flags]
public enum Options : ushort
{
OPTN0 = 1 << 0, // 0001
OPTN1 = 1 << 1, // 0010
OPTN2 = 1 << 2, // 0100
}
Then you can make use of the built-in | operator for enums. You would, however, have to change the signature of your methods to access the Options enum type instead of a ushort.
funcThatUsesOptns(Option.OPTN0 | Option.OPTN1);
[Flags]
public enum MyOptions : ushort {
OPTN0 = 1 << 0,
OPTN1 = 1 << 1,
OPTN2 = 1 << 2,
OPTN3 = 1 << 3,
}
This should do what you want.
I believe the closest you'll get to operator overloading on 2 primitives would be making an extension method. Unfortunately you wouldn't be able to do a true operator overload that way, but it might be an acceptable solution:
public static ushort LogicalOr(this ushort s1, ushort s2)
{
return (ushort)(s1 | s2);
}
funcThatUsesOptns(Option.OPTN1.LogicalOr(Option.OPTN2));
Changing to enum like the other answers is also a good solution if you are OK with changing your function signatures.

Pattern matching F# type in a C# code

Suppose there is a F# definitions:
type Either<'a,'b> = | Left of 'a | Right of 'b
let f (i : int) : Either<int, string> =
if i > 0
then Left i
else Right "nothing"
Function f is used in C# code:
var a = Library.f(5);
How the result value a could be pattern matched for data constructors? Something like:
/*
(if a is Left x)
do something with x
(if a is Right y)
do something with y
*/
Using F# discriminated unions from C# is a bit inelegant, because of how they are compiled.
I think the best approach is to define some members (on the F# side) that will simplify using the types from C#. There are multiple options, but the one I prefer is to define TryLeft and TryRight methods that behave similarly to Int32.TryParse (and so they should be familiar to C# developers using your F# API):
open System.Runtime.InteropServices
type Either<'a,'b> =
| Left of 'a
| Right of 'b
member x.TryLeft([<Out>] a:byref<'a>) =
match x with Left v -> a <- v; true | _ -> false
member x.TryRight([<Out>] b:byref<'b>) =
match x with Right v -> b <- v; true | _ -> false
Then you can use the type from C# as follows:
int a;
string s;
if (v.TryLeft(out a)) Console.WriteLine("Number: {0}", a);
else if (v.TryRight(out s)) Console.WriteLine("String: {0}", s);
You lose some of the F# safety by doing this, but that's expected in a language without pattern matching. But the good thing is that anybody familiar with .NET should be able to use the API implemented in F#.
Another alternative would be to define member Match that takes Func<'a> and Func<'b> delegates and invokes the right delegate with the value carried by left/right case. This is a bit nicer from the functional perspective, but it might be less obvious to C# callers.
I'd define a Match member taking the delegates to execute in each scenario. In F# you'd do it like this (but you could do something equivalent in a C# extension method, if desired):
type Either<'a,'b> = | Left of 'a | Right of 'b
with
member this.Match<'t>(ifLeft:System.Func<'a,'t>, ifRight:System.Func<'b,'t>) =
match this with
| Left a -> ifLeft.Invoke a
| Right b -> ifRight.Invoke b
Now you should be able to do something like this in C#:
var result = a.Match(ifLeft: x => x + 1, ifRight: y => 2 * y);
From the 3.0 spec:
8.5.4 Compiled Form of Union Types for Use from Other CLI Languages
A compiled union type U has:
One CLI static getter property U.C for each null union case C. This property gets a singleton object that represents each such case.
One CLI nested type U.C for each non-null union case C. This type has instance properties Item1, Item2.... for each field of the union
case, or a single instance property Item if there is only one field.
However, a compiled union type that has only one case does not have a
nested type. Instead, the union type itself plays the role of the case
type.
One CLI static method U.NewC for each non-null union case C. This method constructs an object for that case.
One CLI instance property U.IsC for each case C. This property returns true or false for the case.
One CLI instance property U.Tag for each case C. This property fetches or computes an integer tag corresponding to the case.
If U has more than one case, it has one CLI nested type U.Tags. The U.Tags typecontains one integer literal for each case, in increasing
order starting from zero.
A compiled union type has the methods that are required to implement its auto-generated interfaces, in addition to any
user-defined properties or methods.
These methods and properties may not be used directly from F#.
However, these types have user-facing List.Empty, List.Cons,
Option.None, and Option.Some properties and/or methods.
A compiled union type may not be used as a base type in another CLI
language, because it has at least one assembly-private constructor and
no public constructors.
If you can't change the F# api, using points 2 and 4 above you could do it something like this:
C#
class Program
{
static void Main(string[] args)
{
PrintToConsole("5");
PrintToConsole("test");
}
static void PrintToConsole(string value)
{
var result = test.getResult(value);
if (result.IsIntValue) Console.WriteLine("Is Int: " + ((test.DUForCSharp.IntValue)result).Item);
else Console.WriteLine("Is Not Int: " + ((test.DUForCSharp.StringValue)result).Item);
}
}
F#
namespace Library1
module test =
open System
type DUForCSharp =
| IntValue of int
| StringValue of string
let getResult x =
match Int32.TryParse x with
| true, value -> IntValue(value)
| _ -> StringValue(x)
This solution is convenient in that it also handles tuple DU cases by creating a new property for each item in the tuple.

Bitwise subtraction

Given the enum:
[Flags]
enum foo
{
a = 1,
b = 2,
c = 4
}
then
foo example = a | b;
If I don't know if foo contains c, previously I have been writing the following
if (example & foo.c == foo.c)
example = example ^ foo.c;
Is there a way to do this without checking for the existance of foo.c in example?
As when it comes to additions, I can just do an OR, and if the enum value already exists in example then it doesnt matter.
I think you want:
example &= ~foo.c;
In other words, perform a bitwise "AND" mask with every bit set except the one for c.
EDIT: I should add an "except" to Unconstrained Melody at some point, so you could write:
example = example.Except(foo.c);
Let me know if this would be of interest to you, and I'll see what I can do over the weekend...
AND it with the complement of foo.c:
example = example & ~foo.c

F# discriminated unions versus C# class hierarchies

I have the following code:
public abstract class A ...
public class B : A ...
public class C : A ...
void my_fct(A x) {
if (x is B) { block_1 }
else if (x is C) { block_2 }
else { block_3 }
}
and I wonder if it is a good translation from F#
type a = B | C
let my_fct x =
match x with
| B -> ( block_1 )
| C -> ( block_2 )
| _ -> ( block_3 )
??
F# discriminated unions correspond to OO class hierarchies quite closely, so this is probably the best option. The most notable difference is that you cannot add new cases to a discriminated union without modifying the type declaration. On the other hand, you can easily add new functions that work with the type (which roughly corresponds to adding new virtual methods in C#).
So, if you don't expect to add new inherited classes (cases), then this is the best option. Otherwise, you may use F# object types (or other options, depending on the scenario).
One more point regarding your code - since you cannot add new cases, F# compiler knows that the only cases you need are for B and C. As a result, the block_3 can never be executed, which means that you can write just:
let my_fct x =
match x with
| B -> ( block_1 )
| C -> ( block_2 )
yes this is more or less the same as F# does anyhow.
In this case (no values added) - F# seems to translate this into a classs for "a" and some Tags (enumeration). The class for "a" just has some static properties for B and C, and some methods to check if an object of type "a" is "B" or "C" (see below)
But you don't need the "_ -> (block_3)" case, because this can never be matched (F# knows all the possible cases and will warn you).
I think it's better if you throw an exception in C# for this "else" case.

Categories

Resources