C# Enums are always none - c#

In C#, i have the following enum. i want to be able to run my verification function an return the issues found via said enum, but it seems to always contain OK.
everything ive read on this says to use 0 for none, which, to me at least, seems logically equivalent to OK, as there are "none" problems.
but if i check "enum.HasFlag(ValidationResult.OK)" it will return true 100% of the time, no matter how many others are set. i feel like if it doesnt equal 0, it shouldnt say it does. this seems broken to me.
What is the proper way to deal with this?
[Flags]
public enum ValidationResult
{
OK,
NotOK,
ReallyNotOk
}
void Main()
{
var x = ValidationResult.OK;
Console.Write(x.HasFlag(ValidationResult.OK)); // true
var y = ValidationResult.NotOk;
Console.Write(y.HasFlag(ValidationResult.OK)); // still true for some reason
}

0 isn't a flag, it is the complete absence of flags. If the flags represent different types of failures, then it may be appropriate to give the label Ok to 0... but it still isn't a flag and cannot be tested with HasFlag.
Console.Write(y == ValidationResult.OK); // works correctly

namespace EnumTest
{
[Flags]
public enum ValidationResult
{
None = 0,
OK = 1,
NotOK = 2,
ReallyNotOk = 4
}
class Program
{
static void Main(string[] args)
{
ValidationResult x = ValidationResult.OK;
Console.Write(x.HasFlag(ValidationResult.OK)); // true
ValidationResult y = ValidationResult.NotOK;
Console.Write(y.HasFlag(ValidationResult.OK)); // Result False
ValidationResult z = ValidationResult.NotOK | ValidationResult.ReallyNotOk;
Console.Write(z.HasFlag(ValidationResult.OK)); // Result False
}
}
}

In addition to the answer of Ben Voigt, you can fix this by adding desired values manually like:
[Flags]
public enum ValidationResult
{
OK = 1,
NotOK = 2,
ReallyNotOk = 4
}
Update:
As Ben pointed out in his comment, the presented solution lacks the possibility to present EITHER "OK" OR a concrete failure state. Thus I would propose using a class hierarchy instead of an enumeration.
A simple example can be found in the microsoft docs:
Use enumeration classes instead of enum types

Related

HasFlag() always returns true in Enum foreach statement

Thanks for taking the time to try help me.
I've ran into a rather weird issue. I'm trying to loop through all the Enum values to check if my object contains the Enum flag. But for some reason, that I do not quite understand, in the foreach it says it always has the flag. But in the separate if statements it does work exactly how I wanted. But I do not want to repeat code 6 times, so I would like to have the foreach statement working.
Does anybody know what is happening? Maybe some background information why it's happening?
Sorry for my English, it's not my native language.
Thanks in advance!
Code is changed from the original, but it's essentially the same.
Code below.
[Flags]
public enum SampleEnum
{
Enum1 = 0,
Enum2 = 1,
Enum3 = 2,
Enum4 = 4,
Enum5 = 8,
Enum6 = 16,
};
SampleEnum sample = SampleEnum.Enum1 | SampleEnum.Enum2;
// This doesn't work
foreach (SampleEnum enum in Enum.GetValues(typeof(SampleEnum)))
{
// This is statement says it allways has the flags. Even tho it doesn't have the flag.
if(sample.HasFlag(enum))
{
// This is always true.
}
}
// This works
if (sample.HasFlag(SampleEnum.Enum2))
{
// true
}
// This works
if (sample.HasFlag(SampleEnum.Enum3))
{
// false
}
// This works
if (sample.HasFlag(SampleEnum.Enum4))
{
// false
}
}
I seem to recall that having an element with value 0 means that everything contains that when using the HasFlag with [Flags] directive. Try this code:
Enum.GetValues(typeof(MainSettings.ConnectedPrinters)).Cast<MainSettings.ConnectedPrinters>().Where(v => (int)v > 0).ToList())
This will iterate the list without the 0 valued flag.
You should never create Flags enum with a 0 value as it'll do bitwise comparison of the element with 0.
AnyEnumItem & 0 always equals 0.
Edit : Except for an "All item"
From MSDN about HasFlag:
If the underlying value of flag is zero, the method returns true.
You should check for zero before using HasFlag.

Assert that value is equal to any of a collection of expected values

Does NUnit provide a constraint to find whether the actual value is the element of a given enumerable or array, in other words, that it is equal to any of multiple expected values? Something like:
Assert.That(actual, Is.EqualToAnyOf(new[] { 1, 2, 3 }))
That is, to point out, the actual is a single value. I expect the value to be either 1, 2, or 3. The assertion
Assert.That(actual, Contains.Element(expected))
checks logically the same, but it is the opposite intention: Here we have a collection of actual values and expect one value to be in it.
Furthermore, I found these but they all don't fit:
Assert.That(actual, Is.EqualTo(expected)) // only allows one value
Assert.That(actual, Is.InRange(start, end)) // only works for consecutive numbers
Assert.That(actual, Is.SubsetOf(expected)) // only works if actual is an enumerable
Assert.That(expected.Contains(actual)) // meaningless "expected: true but was: false" message
CollectionAssert should be what you need if I am not overlooking something. It is as simple as:
CollectionAssert.Contains(IEnumerable expected, object actual);
However, there seems to be several ways to achieve your goal, such as:
[Test]
public void CollectionContains()
{
var expected = new List<int> { 0, 1, 2, 3, 5 };
var actual = 5;
CollectionAssert.Contains(expected, actual);
Assert.That(expected, Contains.Item(actual));
}
Above assertions should basically assert the same and could be used interchangeably.
Edit:
Question was modified, stating that Assert.That(expected, Contains.Item(actual)); is not valid even though it logically tests the same thing.
There is a way to do this built in to NUnit, using the Or constraint:
Assert.That(actual, Is.EqualTo(1).Or.EqualTo(2).Or.EqualTo(3))
If your list is more dynamic, you can build your list of Ors like this:
var expected = new[] { 1, 2, 3 };
var constraints = Is.EqualTo(expected[0]);
for(var i = 1; i < expected.Length; i++)
constraints = constraints.Or.EqualTo(expected[i]);
Assert.That(actual, constraints);
That latter answer doesn't read as well in the fluid syntax, but does achieve the dynamic building of or constraints. You could probably wrap that in a custom constraint as patrick-quirk demonstrated in order to achieve a more readbale fluid syntax, but that's up to you.
I know this is an old question, bu I have a maybe better (and native) suggestion.
With NUnit 3.x (I'm on 3.10.1) you can use Is.AnyOf:
Assert.That(
actualValue,
Is.AnyOf(expectedValue1, expectedValue2, expectedValue3),
"My error message");
The only way I could see to accomplish this is by creating your own constraint. It's pretty straightforward to do though.
The constraint class itself:
public class OneOfValuesConstraint : EqualConstraint
{
readonly ICollection expected;
NUnitEqualityComparer comparer = new NUnitEqualityComparer();
public OneOfValuesConstraint(ICollection expected)
: base(expected)
{
this.expected = expected;
}
public override bool Matches(object actual)
{
// set the base class value so it appears in the error message
this.actual = actual;
Tolerance tolerance = Tolerance.Empty;
// Loop through the expected values and return true on first match
foreach (object value in expected)
if (comparer.AreEqual(value, actual, ref tolerance))
return true;
// No matches, return false
return false;
}
// Overridden for a cleaner error message (contributed by #chiccodoro)
public override void WriteMessageTo(MessageWriter writer)
{
writer.DisplayDifferences(this);
}
public override void WriteDescriptionTo(MessageWriter writer)
{
writer.Write("either of ");
writer.WriteExpectedValue(this.expected);
}
}
And to make it fluent, create a static method to wrap it (contributed by #chicodorro):
public static class IsEqual
{
public static OneOfValuesConstraint ToAny(ICollection expected)
{
return new OneOfValuesConstraint(expected);
}
}
Then to use it:
int[] expectedValues = new[] { 0, 1, 2 };
Assert.That(6, IsEqual.ToAny(expectedValues));
Fails with the message:
Expected: either of < 0, 1, 2 >
But was: 6

How to use an Enum[]?

In my project i am using an Array of bool which defines the user's access rights.
For example
public bool[] Security {get; set;}
where
[0] = Admin
[1] = GrantWrites
[2] = GrantDeletes
[3] = User
It is working quite well.
I would set it to {F,T,F,T} or {0,1,0,1} and that particular user gets access as a User and it allows him to write.
I am trying to convert it to an enum but apparently i would need an array of it.
currently i have the following (not working)
public class UserCrops
{
public UserCrops(etc.., Enum[] _Security)
{
.
.
.
Security = _Security;
}
.
.
.
public Enum[] Security
{
Admin,
GrantWrites,
GrantDeletes,
User
}
}
I found some links like this but no help.
Thanks in advance
Edit: Both answers are very well explained but I am going with the non-Flag one just because it seems easier for me :)
Edit2: How can i create a new object (outside of class?)
I used to do
bool[] security = new bool[9];
for (int i = 0; i < 9; i++)
{
security[i] = chklstSecurity.Items[i].Selected;
}
userCropList.Add(new UserCrops(.., txtBiologicalAssessmentApprovalDate.Text, security));
But now?
Try with:
[Flags]
public enum Security
{
Admin = 1,
GrantWrites = 2,
GrantDeletes = 4,
User = 8
}
And you'll use it like this:
Security security = Security.GrantWrites | Security.GrantDeletes;
if ((security & Security.GrantWrites) == Security.GrantWrites)
{
}
Comparison can be simplified as pointed out by p.s.w.g. to increase its readability. Moreover I suggest to include a default value in the enum (for when variable is not initialized):
[Flags]
public enum Security
{
None = 0,
Admin = 1,
GrantWrites = 2,
GrantDeletes = 4,
User = 8
}
Finally note that you can provider shortcut for common combinations of flags:
[Flags]
public enum Security
{
// Other values
FullAccess = Admin | GrantWrites | GrantDeletes
}
More of that on MSDN. Please note this approach mimics attributes for file/directories in file system (and many other). IMO is much simpler to use than keep an array of enums as suggested in the other answer:
You do not have to search entire array to check if a permission is granted or not.
You do not have to check for a null value (enum can't be null, an array can be).
It uses less space (even if nowadays this is not so important).
It's naturally (more) safe so less checks are needed (for example to avoid duplicates inside array).
It can be easy stored (as text or integer without additional code).
But it has, compared to that, two main drawbacks:
Flags are finite (32 if you're using an Int32 for your enum or 64 for an Int64).
You can't easily switch to something else (if, for example, Security has to become a class you'll need to write much more code to mimic enums syntax and some assumption made by code when working with enums will be broken).
Remove the [] and use enum instead of Enum:
public enum Security
{
Admin,
GrantWrites,
GrantDeletes,
User
}
And you probably want to use Security[] as a method parameter:
public UserCrops(etc.., Security[] _Security)
Using flags (as Adriano suggests) is an excellent suggestion too, but it will require you to rethink how you're storing your permissions. Instead of storing an array of bool's, you'll represent the entire security set as a single value, with different bits representing each permission.
Read Enumeration Types (C# Programming Guide) under the section Enumeration Types as Bit Flags for more information.

How to identify given int value belongs to which enum

Hi before going to direct problem let me show my code :
//Definition of enum
public enum LogType
{
Warning = -2,
Error = -1,
Info = 0,
EruCtorDtor = 1,
Notifications = 2,
CommunicationWithAOT = 4,
ExecutedOrder = 8,
ERUInfo = 16,
DebugLog = 32,
}
//Use of enum
CurrentLogFlagSettings = nLogFlag;
LogFlagMap = new SortedDictionary<LogType, int>();
ulong mask = 1;
while(mask <= nLogFlag)
{
if ((nLogFlag & mask) == mask)
{
LogType type = (LogType)mask; //Step 1
string val = type.ToString(); //Step 2
//Processing the value
LogFlagMap.Add(type, tempVal)
LogMsg(val + " added", type);
}
mask <<= 1;
}
What I want is : Process step2 only after step1 has produced valid value. I mean value should be between range defined in enum definition. Otherwise I dont want to process it.
for e.g.
case 1 - Lets say mask value is 32,
its defined in enum. So type is
getting value DebugLog and so it
type.ToString() (i.e. "DebugLog"),
this is a valid case.
case 2- Lets
say mask value is 128 and its not
defined in enum, in this case I dont
want to process anything on 128
value. But what is happening its
geting value 128 in type and
type.ToString() is converting it
into 128. I dont want this, I want
to make sure whether 128 belongs to
enum values or not.
I want to prevent 2nd case to be executed. Is there any solution for my problem?
Please let me know if more details are needed.
You could use Enum.IsDefined, like so:
int value = 128;
Console.WriteLine(Enum.IsDefined(typeof(LogType), value)); // will print out False
Firstly, let me seriously apologise, Ive had like no sleep, so if I missed the point a little. Please, just ignore me.
You can enumerate your LogType with Enum.GetValues(typeof(LogType))), so you could step through and check a value against it. I had some code, but, I couldnt promise it compiled.
Bool isValid(int i)
{
foreach (LogType l in Enum.GetValues(typeof(LogType)))
{
if ((int)l == i) return true;
}
return false;
}
You can also use Enum.GetValues(typeof(LogType)) to get all the possible values for your enum and do what you want through that.
i.e.
var values = Enum.GetValues(typeof (LogType));
foreach (LogType type in values)
{
if (((int)type & nLogMask) == (int)type)
{
//value is valid, process the value
}
}
One addition to your code could be the addition of the [Flags] attribute to you enum, this then makes it clear that the enum values are for bitwise operations
e.g.
[Flags]
public enum LogType
{
Warning = -2,
Error = -1,
Info = 0,
EruCtorDtor = 1,
Notifications = 2,
CommunicationWithAOT = 4,
ExecutedOrder = 8,
ERUInfo = 16,
DebugLog = 32,
}
although to do this, you would need to change the values such that the Warning and Error take the top 2 bits of the enum value (assuming this is still necessary).
The c# Enum class also has the method GetName(). This might provide a nice and easy manner to retrieve the name of the value set
e.g.
Enum.GetName( typeof(LogType), 4 ); // result = CommunicationWithAOT
I have a library called Unconstrained Melody which allows you to express all of this in a type-safe generic way and avoids boxing too. Personally I prefer that over using Enum.IsDefined, but obviously that doesn't involve learning an extra library.
It's probably not worth using Unconstrained Melody if this is the only thing you need to do with your enum, but if you've got other similar operations, you may wish to consider it.

How do I specify the exit code of a console application in .NET?

I have a trivial console application in .NET. It's just a test part of a larger application. I'd like to specify the "exit code" of my console application. How do I do this?
Three options:
You can return it from Main if you declare your Main method to return int.
You can call Environment.Exit(code).
You can set the exit code using properties: Environment.ExitCode = -1;. This will be used if nothing else sets the return code or uses one of the other options above).
Depending on your application (console, service, web application, etc.), different methods can be used.
In addition to the answers covering the return int's... a plea for sanity. Please, please define your exit codes in an enum, with Flags if appropriate. It makes debugging and maintenance so much easier (and, as a bonus, you can easily print out the exit codes on your help screen - you do have one of those, right?).
enum ExitCode : int {
Success = 0,
InvalidLogin = 1,
InvalidFilename = 2,
UnknownError = 10
}
int Main(string[] args) {
return (int)ExitCode.Success;
}
There are three methods that you can use to return an exit code from a console application.
Modify the Main method in your application so that it returns an int instead of void (a function that returns an Integer instead of Sub in VB.NET) and then return the exit code from that method.
Set the Environment.ExitCode property to the exit code. Note that method 1. takes precedence - if the Main method returns anything other than void (is a Sub in VB.Net) then the value of this property will be ignored.
Pass the exit code to the Environment.Exit method. This will terminate the process immediately as opposed to the other two methods.
An important standard that should be observed is that 0 represents 'Success'.
On a related topic, consider using an enumeration to define the exit codes that your application is going to return. The FlagsAttribute will allow you to return a combination of codes.
Also, ensure that your application is compiled as a 'Console Application'.
If you are going to use the method suggested by David, you should also take a look at the [Flags] Attribute.
This allows you to do bit wise operations on enums.
[Flags]
enum ExitCodes : int
{
Success = 0,
SignToolNotInPath = 1,
AssemblyDirectoryBad = 2,
PFXFilePathBad = 4,
PasswordMissing = 8,
SignFailed = 16,
UnknownError = 32
}
Then
(ExitCodes.SignFailed | ExitCodes.UnknownError)
would be 16 + 32. :)
System.Environment.ExitCode
See Environment.ExitCode Property.
int code = 2;
Environment.Exit( code );
Just return the appropiate code from main.
int Main(string[] args)
{
return 0; // Or exit code of your choice
}
Use ExitCode if your main has a void return signature. Otherwise, you need to "set" it by the value you return.
From Environment.ExitCode Property:
If the Main method returns void, you can use this property to set the exit code that will be returned to the calling environment. If Main does not return void, this property is ignored. The initial value of this property is zero.
The enumeration option is excellent. However, it can be improved upon by multiplying the numbers as in:
enum ExitCodes : int
{
Success = 0,
SignToolNotInPath = 1,
AssemblyDirectoryBad = 2,
PFXFilePathBad = 4,
PasswordMissing = 8,
SignFailed = 16,
UnknownError = 32
}
In the case of multiple errors, adding the specific error numbers together will give you a unique number that will represent the combination of detected errors.
For example, an errorlevel of 6 can only consist of errors 4 and 2, 12 can only consist of errors 4 and 8, 14 can only consist of 2, 4 and 8 etc.
As an update to Scott Munro's answer:
In C# 6.0 and VB.NET 14.0 (Visual Studio 2015), either Environment.ExitCode or Environment.Exit(exitCode) is required to return an non-zero code from a console application. Changing the return type of Main has no effect.
In F# 4.0 (Visual Studio 2015), the return value of the main entry point is respected.
You can find the system error codes on System Error Codes (0-499).
You will find the typical codes, like 2 for "file not found" or 5 for "access denied".
And when you stumble upon an unknown code, you can use this command to find out what it means:
net helpmsg decimal_code
For example,
net helpmsg 1
returns
Incorrect function
Use this code
Environment.Exit(0);
use 0 as the int if you don't want to return anything.
I'm doing it like this:
int exitCode = 0;
Environment.Exit(exitCode);
Or you can throw an error (personal preference):
throw new ArgumentException("Code 0, Environment Exit");
I've choose ArgumentException, but you can type other. It will work fine.
Just another way:
public static class ApplicationExitCodes
{
public static readonly int Failure = 1;
public static readonly int Success = 0;
}

Categories

Resources