Compare Enums in if statement - c#

I want to compare some enums on ifs statements here is what I mean but this isnt working. Basically I want to see if the injury is the same as the enum so if for example the injury is bleeding you need to bandage etc. If you need any other information please let me know.
static string injuries = GetInjuriesName(GetInjuries(closestPlayer));
EPedInjuries result;
if (Enum.TryParse(injuries, out result) && result == EPedInjuries.Overdose)
{
.....
}
else if (Enum.TryParse(injuries, out result) && result == EPedInjuries.GunShotWound)
{
....
}
....
public enum EPedInjuries
{
OpenFracture,
GunShotWound,
Fever,
BrokenLeg,
BrokenArm,
BrokenRib,
Overdose,
.....
}
public static EPedInjuries GetInjuries(Ped ped)
{
Ped = ped;
int num = API.Common.Random.Next(0, 101);
if (num >= 0 && num <= 37)
{
return EPedInjuries.Overdose;
}
if (num > 37 && num <= 55)
{
return EPedInjuries.GunShotWound;
}
if (num > 55 && num <= 72)
{
return EPedInjuries.CardiacArrest;
}
....
}
public static string GetInjuriesName(EPedInjuries injuries)
{
string result = string.Empty;
switch (injuries)
{
case EPedInjuries.Overdose:
result = "~r~Overdose";
break;
case EPedInjuries.GunShotWound:
result = "~r~Gunshot Wound";
break;
case EPedInjuries.CardiacArrest:
result = "~r~Cardiac Arrest";
break;
....
}
return result;
}

The GetInjuries method already returns the enum type you want to compare. As #Johnny Mopp points out, you are getting the enum, converting it to some string, only to try to convert it back to an enum
Just do
EPedInjuries result = GetInjuries(closestPlayer);
if (result == EPedInjuries.Overdose)
{
.....
}
else if (result == EPedInjuries.GunShotWound)
{
....
}

Your GetInjuriesName returns string which is not correct enum value and Enum.TryParse can't parse it and returns false:
var injuries = GetInjuriesName(EPedInjuries.Overdose);
Console.WriteLine(injuries); //prints "~r~Overdose"
Console.WriteLine(Enum.TryParse(injuries, out EPedInjuries result)); // prints "False"
Just introduce two fields/variables one for name and one for injury enum value:
EPedInjuries injury = GetInjuries(closestPlayer)
string injuryName = GetInjuriesName(injury);
And use the first one to handle the logic:
if(injury == EPedInjuries.Overdose)
{
....
}
.....

I believe you will receive strings from somewhere else so you want to convert that's why you have that GetInjuriesName method. For me, you should just switch on the strings you receive.
For the sake of fixing this code, you should remove the "~r~" from the strings so that it matches any enum type.
Also, enums can't be null so you will always get the first value which is the Default.
public static string GetInjuriesName(EPedInjuries injuries)
{
string result = string.Empty;
switch (injuries)
{
case EPedInjuries.Overdose:
result = "Overdose";
break;
case EPedInjuries.GunShotWound:
result = "Gunshot Wound";
break;
case EPedInjuries.CardiacArrest:
result = "Cardiac Arrest";
break;
}
return result;
}
Then the TryParse will work and produce a value contained inside the enum.

Related

C# - Compare two strings by using dots in the strings and using wildcards: *

I have two string variables that i want to compare.
var compareA = "something.somethingelse.another.something2"
var compareB = "*.another.something2"
I want to compare this, and the result is: True.
var compareC = "something.somethingelse.*"
compared to compareA, the result should also be: True.
Of course, the fact that both variables can contain N dots also complicates the task.
How would you start for him?
I was tried this:
static void Main(string[] args)
{
var A = CompareString("*.something", "other.Another.something"); //I need this is true!
var B = CompareString("something.Value.Other.*", "something.Value.Other.SomethingElse"); //I need this is true
var C = CompareString("something.Value.Other", "something.Value.Other.OtherElse"); //I need this is False
var D = CompareString("*.somethingElse", "other.another.Value"); //I Need this is false
Console.WriteLine("It is need True: {0}", A);
Console.WriteLine("It is need True: {0}", B);
Console.WriteLine("It is need False: {0}", C);
Console.WriteLine("It is need False: {0}", D);
}
private static bool CompareString(string first, string second)
{
var resume = false;
var firstSplit = first.Split('.');
var secondSplit = second.Split('.');
foreach (var firstItem in firstSplit)
{
foreach (var secondItem in secondSplit)
{
if (firstItem == "*" || secondItem == "*" || string.Equals(firstItem.ToLower(), secondItem.ToLower()))
{
resume = true;
}
else
{
resume = false;
}
}
}
return resume;
}
The results are good, but I think it can be done differently, and the reasoning may be wrong.
Assuming the following:
Compare 1 string to another and it's the full string of 1 contained inside the longer of the 2 strings.
Case to be ignored as well as culture.
The full stops are considered part of the string, not actually as a separator.
Wildcards can be used to state how 1 string can be contained within another.
You should be able to use the following
private bool HasMatch(string textToSearch, string searchText)
{
if (textToSearch.Length < searchText.Length) return false;
var wildCardIndex = searchText.IndexOf('*');
if (wildCardIndex == -1)
{
return textToSearch.Equals(searchText, StringComparison.InvariantCultureIgnoreCase);
}
else
{
if (wildCardIndex == 0)
{
var text = searchText.TrimStart('*');
return textToSearch.EndsWith(text, StringComparison.InvariantCultureIgnoreCase);
}
if (wildCardIndex == (searchText.Length - 1))
{
var text = searchText.TrimEnd('*');
return textToSearch.StartsWith(text, StringComparison.InvariantCultureIgnoreCase);
}
}
return false;
}

Convert VBA select case to C#

Select Case True
Case Not A.Name Is Nothing
Set Name = A.Name
Case Not A.Age Is Nothing
Set Age = A.Age
Case Not A.School Is Nothing
Set School = A.School
End Select
In VB Select Case True is allowed to use. But for C# it gives an error. How can I convert this VB code to C# ?
There is no direct analog in C# because C# case labels must be constant expressions. Select Case True is an unusual construct that serves as an alternative to if-else constructs.
I suggest replacing it with the far more common pattern:
if (A.Name != null)
Name = A.Name;
if (A.Age != null)
Age = A.Age;
// ... etc
Using switch case in c# is some different. I think this example can be able to useful to you.
using System;
using System.Collections.Generic;
using System.Linq;
public class Example
{
public static void Main()
{
var values = new List<object>();
for (int ctr = 0; ctr <= 7; ctr++) {
if (ctr == 2)
values.Add(DiceLibrary.Roll2());
else if (ctr == 4)
values.Add(DiceLibrary.Pass());
else
values.Add(DiceLibrary.Roll());
}
Console.WriteLine($"The sum of { values.Count } die is { DiceLibrary.DiceSum(values) }");
}
}
public static class DiceLibrary
{
// Random number generator to simulate dice rolls.
static Random rnd = new Random();
// Roll a single die.
public static int Roll()
{
return rnd.Next(1, 7);
}
// Roll two dice.
public static List<object> Roll2()
{
var rolls = new List<object>();
rolls.Add(Roll());
rolls.Add(Roll());
return rolls;
}
// Calculate the sum of n dice rolls.
public static int DiceSum(IEnumerable<object> values)
{
var sum = 0;
foreach (var item in values)
{
switch (item)
{
// A single zero value.
case 0:
break;
// A single value.
case int val:
sum += val;
break;
// A non-empty collection.
case IEnumerable<object> subList when subList.Any():
sum += DiceSum(subList);
break;
// An empty collection.
case IEnumerable<object> subList:
break;
// A null reference.
case null:
break;
// A value that is neither an integer nor a collection.
default:
throw new InvalidOperationException("unknown item type");
}
}
return sum;
}
public static object Pass()
{
if (rnd.Next(0, 2) == 0)
return null;
else
return new List<object>();
}
}
You can give more information here about switch case
Your VBA code mimics an If-Then-ElseIf ... block, so how about:
if (A.Name != null)
{
Name = A.Name;
}
else if (A.Age != null)
{
Age = A.Age;
}
else if (A.School != null)
{
School = A.School;
}

Get a variable value from a method to another?

In this situation, I am trying to get the value of "FileSizeType", an integer variable, into the method that's under it "NomCategorie"and convert it to a string(that's what the comment says).
static int ChoisirCategory()
{
int FileSizeType;
Console.Write("What type do you want: ");
FileSizeType = Convert.ToInt32(Console.ReadLine());
return FileSizeType;
}
static string NomCategorie(int c)
{
//get FileSizeType into c
string FileType;
if (c == 1)
{
return FileType = "Small";
}
else if (c == 2)
{
return FileType = "Medium";
}
else if (c == 3)
{
return FileType = "Large";
}
else if (c == 4)
{
return FileType = "Huge";
}
else
{
return FileType="Non-valid choice";
}
I would suggest using enum class
public enum Test
{
Small = 1,
Medium = 2,
Large = 3,
Huge = 4
}
then you can simply convert the number by using
int integer = 1;
if (Enum.IsDefined(typeof(Test), integer)
{
Console.WriteLine((Test)integer).
}
else
{
Console.WriteLine("Bad Integer");
}
output:
Small
Looking at your existing code, you are already returning the value of FileSizeType from the ChoisirCategory, so you can capture it in a variable and then pass that to the NomCategorie method to get the category name, for example:
int categoryId = ChoisirCategory();
string categoryName = NomCategorie(categoryId);
Note that there are many other improvements that can be made (for example, what happens if the user types in "two" instead of "2"?), but I think those suggestions may be out of scope based on the question.
Here's how your code could be simplified if you combine both suggestions above. I've also added an if clause to verify that the value is not higher than those available.
static enum AvailableSizes
{
Small = 1,
Medium = 2,
Large = 3,
Huge = 4
}
static int ChoisirCategory()
{
int FileSizeType;
GetInput:
Console.Write("What type do you want: ");
FileSizeType = Convert.ToInt32(Console.ReadLine());
// Ensure the value is not higher than expected
// (you could also check that it is not below the minimum value)
if (FileSizeType > Enum.GetValues(typeof(AvailableSizes)).Cast<int>().Max());
{
Console.WriteLine("Value too high.");
goto GetInput;
}
return FileSizeType;
}
static string NomCategorie(int c)
{
if (Enum.IsDefined(typeof(AvailableSizes), c)
{
return (AvailableSizes)c;
}
else
{
return "Invalid category";
}
}
Then somewhere in your code you would call these using this statement
string categoryStr = NomCategorie(ChoisirCategory());
Console.WriteLinte(categoryStr); // or do whatever you want with the returned value
With this code, if the input is higher than 4, it will output "Value too high." and ask the question again until the value is no higher than 4.
If the user types 0 or a negative value, then it will output "Invalid category".
This might help you decide where you want to handle input errors: right after user input or during the parsing of the number to a string.

Is there an easier way to parse an int to a generic Flags enum?

I've got a generic function to parse an object into a generic Enum.
However, I'm running into an issue when trying to safely parse an int into a [Flags] Enum.
Directly using Enum.ToObject() works to parse valid combinations, but will just return the original value if there isn't a flag combination.
Additionally, when there's no explicit enum member for a combination of flags, Enum.ToName() and Enum.IsDefined() don't return helpful values.
For Example:
[Flags]
public enum Color
{
None = 0,
Red = 1,
Green = 2,
Blue = 4,
}
// Returns 20
Enum.ToObject(typeof(Color), 20)
// Returns ""
Enum.ToName(typeof(Color), 3)
// Returns false
Enum.IsDefined(typeof(Color), 3)
I've written a function that I think technically works, but it seems like there has to be a better way to do this.
My Function:
public static T ParseEnumerator<T>(object parseVal, T defaultVal) where T : struct, IConvertible
{
Type ttype = typeof(T);
if (!ttype.IsEnum)
{
throw new ArgumentException("T must be an enumerated type");
}
bool isFlag = ttype.GetCustomAttribute(typeof(FlagsAttribute)) != null;
try
{
if (parseVal == null)
{
return defaultVal;
}
else if (parseVal is T)
{
return (T)parseVal;
}
else if (parseVal is string)
{
return (T)Enum.Parse(ttype, parseVal.ToString(), true);
}
//**************** The section at issue **********************************/
else if (isFlag && parseVal is int)
{
List<string> flagsList = new List<string>();
int maxVal = 0;
//Loop through each bit flag
foreach (var val in Enum.GetValues(ttype))
{
if (CountBits((int)val) == 1)
{
if ((int)val > maxVal)
maxVal = (int)val;
// If the current bit is set, add the flag to the result
if (((int)parseVal & (int)val) == (int)val)
{
string enumName = Enum.GetName(ttype, val);
if (!string.IsNullOrEmpty(enumName))
flagsList.Add(enumName);
}
}
}
// Is the value being parsed over the highest bitwise value?
if ((int)parseVal >= (maxVal << 1))
return defaultVal;
else
return (T)Enum.Parse(ttype, string.Join(",", flagsList));
}
//************************************************************************/
else
{
string val = Enum.GetName(ttype, parseVal);
if (!string.IsNullOrEmpty(val))
return (T)Enum.ToObject(ttype, parseVal);
else
return defaultVal;
}
}
catch
{
return defaultVal;
}
}
Is there something I'm missing? Or is there another way to parse these values safely?
Any help is appreciated, thanks!
-MM
Since your generic function has to know the Enum type to begin with, you can just scrap the function and use basic casting instead.
using System;
namespace SO_58455415_enum_parsing {
[Flags]
public enum CheeseCharacteristics {
Yellow = 1,
Mouldy = 2,
Soft = 4,
Holed = 8
}
public static class Program {
static void Main(string[] args) {
CheeseCharacteristics cc = (CheeseCharacteristics)12;
Console.WriteLine(cc);
}
}
}
If all you want to know is if you have a value that can be created using the enum flags.. that's pretty easy, as long as we can assume that each flag is "sequential" (e.g. there are no gaps between the flags). All numbers between 1 and the sum of all flag values can be made by some combination of flags. You can simply sum the flag values together and compare that to your question value.
public static bool IsValidFlags<T>(int checkValue) where T:Enum {
int maxFlagValue = ((int[])Enum.GetValues(typeof(T))).Sum();
return (0 < checkValue) && (checkValue <= maxFlagValue);
}
For future reference, you can constrain your generic parameter to an enum:
void fx<T> () where T:Enum { }

Can a return statement returning the result of a ternary expression be made to not return for one branch of the ternary?

Is it possible to write this if statement in ternary operator (shorthand of c# if)? If yes what would it be?
if (condition)
{
return true;
}
else
{
int a = 2;
}
Thanx everyone in advance. Thank you very much.
Sorry guys if I confused you. I am trying to use ternary operator in this if else block of the method.
public static bool CompareDictionary(this Dictionary<Position, char>
dictionary1,
Dictionary<Position, char> dictionary2, out List<string> wordList)
{
string str = "";
wordList = new List<string>();
foreach (var dic1KeyVal in dictionary1)
{
Position d1key = dic1KeyVal.Key;
char d1Pos = dic1KeyVal.Value;
bool isFound = false;
foreach (var dic2KeyVal in dictionary2)
{
Position d2key = dic2KeyVal.Key;
char d2Pos = dic2KeyVal.Value;
if (d1Pos.Equals(d2Pos) && d1key == d2key)
{
isFound = true;
str = str + d1Pos.ToString();
}
}
if (isFound == false)
{
return false;
}
else
{
wordList.Add(str);
str = "";
}
}
return true;
}
Short Answer
No.
Long Answer
First of all this code does not even need an else:
if (condition)
{
return true;
}
else
{
int a = 2;
}
and can be written as:
if (condition)
{
return true;
}
int a = 2;
Now for ternary operator: Both conditions in a ternary operator must return the same thing. You cannot return a bool in one condition and then assign to a variable in another condition. If you were checking the answer to a question, for example, it would be like this:
return answer == 2 ? true : false;
Whether the answer is correct or not, we return a bool. Or it could be like this:
return answer == 2 ? 1: -1;
But not like this:
return answer == 2 ? true : "wrong"; // will not compile
No. The ternary operator just returns one out of two potential values depending on a condition.
What you can do with the ternary operator is, e.g. int a = condition ? 0 : 2 which would assign the variable a value of either 0 or 2 depending on the value of condition.
Given a more complete example of what you intend to do someone here could potentially come up with a nicer syntax.

Categories