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.
Related
This question already has answers here:
What does the [Flags] Enum Attribute mean in C#?
(14 answers)
Closed 7 years ago.
Say I have an enum defined like so:
[Flags]
public enum LogLevel
{
None = 1,
Pages = 2,
Methods = 4,
Exception =8
}
and a class like:
public static class Log
{
public static LogLevel Level = LogLevel.Methods | LogLevel.Pages;
public static void EnterPage([CallerFilePath]string filePath = "")
{
if (Level == //What value here to check if Level includes Pages?)
{
//Log
}
}
What value do I need to equate Level to to check whether the enum includes Pages?
First of all, flags must have a None = 0 value, because otherwise there's no way to represent a 0 mask (i.e. no value).
Once you've fixed it, you can check if some enumeration value is in some given flag using Enum.HasFlag or the bit-wise & operator:
Level.HasFlag(LogLevel.Pages);
...or:
(Level & LogLevel.Pages) == LogLevel.Pages
Finally, when you implement a flags enumeration, usually enumeration identifier is expressed in plural. In your case, you should refactor LogLevel to LogLevels.
Why &?
Each enumeration value represents a bit in a complete mask. For example, None would be 0, but it could be also represented as 0, 0, 0 where each 0 is one of possible enumeration values in LogLevels. When you provide a mask like LogLevels.Pages | LogLevels.Methods, then the mask is 1, 1, 0.
In order to check if Pages is within the mask, you use a logical AND comparing the mask with one of possible enumeration values:
1, 1, 0 (LogLevels.Pages | LogLevels.Methods)
1, 0, 0 AND (LogLevels.Pages)
--------
1, 0, 0
1 and 1 (true and true == true)
1 and 0 (true and false == false)
0 and 0 (false and false == false).
The whole AND is like isolating the tested enumeration value. If the resulting mask equals the enumeration value, then the mask contains the enumeration value.
Some OP concern
OP said in some comment:
Just a quick question on zero value. here it states that You cannot
use the None enumerated constant in a bitwise AND operation to test
for a flag because the result is always zero. Does that mean if I have
a 0 value I cannot use & and must use HasFlag?
None (i.e. 0) won't be a member of a mask, because 0 doesn't exist. When you produce a mask you're using the OR | logical operator, which is, at the end of the day, an addition.
Think about 1 + 0 == 1. Would you think checking if 0 is within 1 is ever possible?
Actually, the None = 0 value is required to be able to represent and empty mask.
Finally, HasFlag does the AND for you, it's not a magical solution, but a more readable and encapsulated way of performing the so-called AND.
like this
if (Level.HasFlag(LogLevel.Pages))
{
//todo
}
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;
I have the following code:
namespace ConsoleApplication1
{
internal class Program
{
[FlagsAttribute]
private enum RenderType
{
DataUri = 0,
GZip = 1,
ContentPage = 2,
ViewPage = 4,
HomePage = 8
}
private static void Main()
{
// 4.
// Set a new enum in three statements.
RenderType type2 = RenderType.ViewPage;
// 5.
// See if the enum contains this flag.
if ((type2 & RenderType.ViewPage) == RenderType.ViewPage)
{
Console.WriteLine("ViewPage");
}
if ((type2 & RenderType.DataUri) == RenderType.DataUri)
{
Console.WriteLine("DataUri");
}
if ((type2 & RenderType.GZip) == RenderType.GZip)
{
Console.WriteLine("GZip");
}
}
}
}
Whenever I run this code, it gives me an output of:
ViewPage
DataUri
I want output of just ViewPage as I am giving the value to my enum ViewPage.
Can anyone help me here? Why is this? Is there anything wrong with my Enum declaration or code?
You have declared DataUri = 0 so
(type2 & RenderType.DataUri) == RenderType.DataUri
will always evaluate to true.
Start your valid enum values at 1.
Any number bitwise anded with zero is zero. Start the enum with one and increase by powers of two. Also, a better understanding of binary numbers and bitwise operators will help
DataUri is 0: so x & DataUri is always zero!
Try this:
if(type2 != RenderType.DataUri) {
if ((type2 & RenderType.ViewPage) == RenderType.ViewPage)
{
Console.WriteLine("ViewPage");
}
if ((type2 & RenderType.GZip) == RenderType.GZip)
{
Console.WriteLine("GZip");
}
}
When using Bitmasks the value 0 usually indicates a NONE-Flag. So you should start to count from 1 to 2^n, which is a better practise IMHO:
[FlagsAttribute]
private enum RenderType
{
None = 0,
DataUri = 1,
GZip = 2,
ContentPage = 4,
ViewPage = 8,
HomePage = 16
}
Because x & 0 always equals zero.
Don't specify 0 (zero) as a possible value for a [Flags] enum. Remember that a [Flags] enum is a bit field, and a value of zero doesn't really map into any of the fields, so it will always return true.
From the Framework Design Guidelines by Krzysztof Cwalina:
Avoid using flag enum values normal members that are negative or zero.
Negative values produce unexpected/confusing results in bitwise operations. An enum value of zero creates problems with and operations, etc:
The reason is that RenderType.DataUri has the value 0.
What your code does is to inspect the bitwise configuration of the type2 enum variable by performing a bitwise and operation between type2 and the enum member it's testing for.
In your example, type2 has the value 4, which is 0100 in binary (up to the 4 bits that your enum requires). When you test for RenderType.GZip (0001), it does the following calculation:
0100 & 0001 = 0000
Since 0000 != 0001, the RenderType.GZip bit is not set in type2. However, 0100 & 0000 is always 0000, so you'll always get true when checking for RenderType.DataUri.
Essentially, a Flags enum uses a different bit for each of its members, but since 0 doesn't represent a bit in an integer, it won't behave as expected.
As others have said you should start Flags enums at 1 due to how binary arithmetics work. I just want to add that you may want to use the HasFlag method (I believe new in .NET 4.0) to check the flags:
if(type2.HasFlag(RenderType.ViewPage))
{
...
}
http://msdn.microsoft.com/en-us/library/system.enum.hasflag.aspx
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
This is one of the most used Regex functions
Regex.IsMatch("Test text for regex test.", "(test)",
RegexOptions.IgnoreCase | RegexOptions.Multiline);
Can you explain how Regex.IsMatch method works ?
I mean how it handles bitwise OR RegexOptions parameters ?
How it defines method parameters ?
Thanks for replies !
RegexOptions is an enumeration with the [Flags] attribute applied to it. This allows bitwise operations to be applied to the various values.
You can also do something similar:
[Flags]
enum MyOptions {
UpperCase = 1,
Reverse = 2,
Trim = 4
}
public static void DoTransform(MyOptions options) {
if ((options & MyOptions.UpperCase) == MyOptions.UpperCase) {
/* Do Upper case transform */
}
if ((options & MyOptions.Reverse) == MyOptions.Reverse) {
/* Do Reverse transform */
}
/* etc, ... */
}
DoTransform(MyOptions.UpperCase | MyOptions.Reverse);
I've just done a bit more digging based on Frank's comment and he is correct that with or without the [Flags] attribute, the code above will compile and run.
There have been other comments in regard to what the [Flags] attribute does not do but other than "it affects the ToString() result" no one seems to know or wants to explain what it does do. In code I write, I adorn enumerations that I intend to use as bitfields with the [Flags] attribute, so in that case it is at least somewhat self-documenting. Otherwise, I'm at a loss.
RegexOptions is an enumeration, meaning that internally, it's represented as an integer. The values of it look something like this:
// note the powers of 2
enum RegexOptions {
IgnoreCase = 1, MultiLine = 2,
SomeOtherOption = 4, YetAnotherThing = 8 }
The values are designed so that if you express them in binary, each one has a single bit on.
Because of this, if you take the bitwise OR of two values and end up with a result, you can figure out if one of the values is set (e.g. IgnoreCase) by evaluating (result AND IgnoreCase).