C#: Getting an enum value by string? - c#

I'm trying to get a enum value from a string in a database, below is the enum I am trying to get the value from, the DB value is a string.
internal enum FieldType
{
Star,
Ghost,
Monster,
Trial,
None
}
Heres the DB part:
using (var reader = dbConnection.ExecuteReader())
{
var field = new Field(
reader.GetString("field_type"),
reader.GetString("data"),
reader.GetString("message")
);
}
Now, I had this method that did it for me, but it seems overkill to have a method do something that C# could already do, can anyone tell me if theres a way I can do this within the C# language without creating my own method?
public static FieldType GetType(string Type)
{
switch (Type.ToLower())
{
case "star":
return FieldType.Star;
case "ghost":
return FieldType.Ghost;
case "monster":
return FieldType.Monster;
case "trial":
return FieldType.Trial;
default:
case "none":
return FieldType.None;
}
}

In essence, I believe what you need is parsing from string to an enum. This would work if the value of the string is matching the enum value (in which it seems it is here).
Enum.TryParse(Type, out FieldType myFieldType);
Enum.TryParse(Type, ignoreCase, out FieldType myFieldType);
First method case-sensitive while the second allows you to specify case sensitivity.
How should I convert a string to an enum in C#?

Let's define a test string first:
String text = "Star";
Before .NET 4.0 (MSDN reference):
// Case Sensitive
FieldType ft = (FieldType)Enum.Parse(typeof(FieldType), text, false);
// Case Insensitive
FieldType ft = (FieldType)Enum.Parse(typeof(FieldType), text, true);
but with Enum.Parse you have to manage a potential exception being thrown if the parsing process fails:
FieldType ft;
try
{
ft = (FieldType)Enum.Parse(typeof(FieldType), text, true);
}
catch (Exception e)
{
ft = FieldType.None;
}
Since .NET 4.0 (MSDN reference):
FieldType ft;
// Case Sensitive
if (!Enum.TryParse(text, false, out ft))
ft = FieldType.None;
// Case Insensitive
if (!Enum.TryParse(text, true, out ft))
ft = FieldType.None;

Related

if string value is used in case then we not need to convert there format before comparison?

I have used below code in a project and someone ask me to use ToLower() or ToUpper() and I think it is unnecessary.
public somefun(Classabc clsabc, string emptype, string id)
{
switch(emptype)
{
case :"AnyInput":
{
//do
}
break;
case :"StringInput":
{
//do
}
break;
}
}
if(emptype=="AnyInput")
{
///
}
Is the above perfect or we need to use ToLower() or ToUpper() with empType in if()? Is there any issue or programming rule violation with my code? According to me in case (switch) we are using email type as constant for case matching and if emptype value can be used in case matching then there is no need to add extra functions to convert to there case before string matching.
Depends on what you guys are looking for.
If the comparison is case sensitive, you can keep the switch-case comparison like you did in the example you provided.
In case the comparison is insensitive, you can pattern matching (C# 7 and above) and write something like this:
switch (true)
{
case bool b when emptype.Equals("AnyInput", StringComparison.InvariantCultureIgnoreCase):
// do
break;
case bool b when emptype.Equals("StringInput", StringComparison.InvariantCultureIgnoreCase):
// do
break;
default:
break;
}

String.Empty in Switch/case statement generate a compiler error

If String.Empty is as good as "", then how come the compiler throws up with string.Empty in the case statement? Nothing can be more constant than string.Empty in my view. Anyone know? Thanks!
switch (filter)
{
case string.Empty: // Compiler error "A constant value is expected"
break;
case "": // It's Okay.
break;
}
You can try like this instead:
switch(filter ?? String.Empty)
string.Empty is a read-only field whereas "" is a compile time constant. You can also go through a article here on Code Project String.Empty Internals
//The Empty constant holds the empty string value.
//We need to call the String constructor so that the compiler doesn't
//mark this as a literal.
//Marking this as a literal would mean that it doesn't show up as a field
//which we can access from native.
public static readonly String Empty = "";
On a side note:
You will also see this issue when you are providing the default parameter value inside your method(C# 4.0):
void myMethod(string filter = string.Empty){}
The above will result in a compile time error as the default value needs to be a constant.
The reason is: you cannot use readonly values in case: consider the following scenario:
public string MyProperty { get; } // is a read-only property of my class
switch (filter)
{
case MyProperty: // wont compile this since it is read only
break;
// rest of statements in Switch
}
As you said string.Empty is equivalent to "", here I can prove this with the same example of a switch statement:
string filter = string.Empty;
switch (filter)
{
case "": // It's Okay.
break;
//rest of statements in Switch
}
Then the only reason it won't allow string.Empty in case it is read-only, the switch won't allow read-only values in its case.

Converting a value from an expression to another type C#

I'm coding a custom query builder from expressions, and at some point I'm saving the value of an expression to my criteria class:
switch(expression.NodeType)
{
case ExpressionType.Constant:
{
//Here there should only be raw values
CriteriaClass newCriteria = new CriteriaClass();
newCriteria.Value = expression; //Value is of 'object' type
return newCriteria;
}
}
And when I'm actually setting up the query, I have a list of all criterias and their values, which seem fine but... their types are all messed up.
The problem is that my next step is converting properly the types of values to the specific DB format:
private string FormatWriteValue(object value, Type type)
{
if (value == null) { return "NULL"; }
if (value.GetType().IsEnum) { return ((int)value).ToString(); }
switch(type.Name)
{
case "Boolean":
case "bool":
return ((bool)value) ? "1" : "0";
case "Int32":
case "int":
return value.ToString();
case "DateTime":
return "CONVERT(DATETIME, '" + ((DateTime)value).ToString("dd/MM/yyyy hh:mm:ss") + "', 103)";
default:
return "'" + value.ToString().Replace("'", "''") + "'";
}
}
Since the type is never one of the basic ones I've typed there, it always falls on the default case for strings.
I've tried casting the value of the expression like this:
criteria.Value = (int)expression; //exception
criteria.Value = Convert.ChangeType(expression, expression.Type); //Type = Int32, but exception again
criteria.Value = Expression.Convert(expression, expression.Type); //Becomes Unary, no exception
I think for the last one to work I'd have to compile the expression, but I've read that it's costly and I'd like to keep this as light as possible.
How can I accomplish this?
When you create your LINQ query to create your data, verify what type of data it is.
So for instance when you do confirm the type, you can parse a string into a DateTime struct like this :Parse string to DateTime in C#
The best thing to do with your LINQ.Expression type is this: Convert it into a string. Then convert that string dynamically into the type you need.
var criteriaToBeConverted = Expression.Call(
Expression.Convert(memberExpression, typeof(object)),
typeof(object).GetMethod("ToString"));
You can learn more about Expression here : http://msdn.microsoft.com/fr-fr/library/system.linq.expressions.expression.call(v=vs.110).aspx
The provided code comes from this actual answer : LINQ Expression Conversion / Concat from Int to string
When you have type as a string, create a method which reads the string and verifies what type the string represents and parse it. Then you return the value as an object.
Hope it helps you out !
If the answer helps you in anyway, check it as answer so others with the same problem can know what to do !

Is it possible to parse "-1.#IND", etc using Double.Parse method

Trying to use System.Double.Parse(string) method for strings such as "-1.#IND" and "INF" representing special values results in a FormatException.
Is there any built-in .NET framework support to parse these?
No, the only non-numeric values double.Parse recognizes are the string values returned by double.Nan.ToString(), double.PositiveInfinity.ToString(), and double.NegativeInfinity.ToString() (dependent on Culture).
In your case I would just use a switch:
double dblValue;
switch strValue
{
case "-1.#IND":
dblValue = double.Nan;
break;
case "INF":
dblValue = double.Infinity;
break;
//... other casess
default:
dblValue = double.Parse(strValue);
break;
}
NaN and other values are parsed in the specified culture (or neutral, if no culture is specified). You can play with those here if you want.
If you have to parse something more special, then just
public double MyParse(string text)
{
if(text == "blablabla")
return double.NaN;
if(text.Contains("blablabla")) ...
if(text.StartsWith(...
return double.Parse(text);
}

Using an enum and a switch statement c#

I am using an enum as my options for a switch statement and it works. The problem is if the user enter a non valid option the program crashes. What should I add so that the default is used?
my enum class
public enum Options : byte
{
Display = 1,
Add,
Toggle,
Max,
Mean,
Medium,
Exit
}
in main my switch statement
string volString = Console.ReadLine();
Options options = (Options)Enum.Parse(typeof(Options), volString);
// this is the line that is giving me the runtime error. Since other options are not found
in the enum the program crashes.
switch (options)
{
case Options.Display: //dispaly regular time
case Options.Toggle://toggle
default:
Console.WriteLine("entry blah blah");
break;
Instead of Enum.Parse use Enum.TryParse... this will return a boolean to say if the text can be converted into your enum. If it's true run your switch otherwise inform the user that they entered an invalid string.
Use Enum.TryParse instead:
Options options;
if(!Enum.TryParse(volString, out options)) {
// It wasn't valid input.
}
How about:
Options value;
if(!Enum.TryParse(volString, out value)) // note implicit <Options>
value = Options.SomeDefaultValue;
Look at Enum.TryParse(...) you can use this to check for invalid strings.

Categories