I have a set of objects named something like this:
_1,_2,_3 .... _n
Isn't an array, just a bunch of objects uinto a custom control. I want to cast the name to an int. first I remove _, but If use
private void Superficie_MouseDown(object sender, MouseButtonEventArgs e)
{
int index = 0;
Shape myShape = ((Shape)sender);
string lcNombre = myShape.Name.Remove(0, 1);
//--------------------------------------------------------------------
// Those are my tryes
// Doesn't work because it must expect a nullable value
index = lcNombre as decimal;
// Doesn't work Can't convert string to int
index = (int)lcNombre;
//--------------------------------------------------------------------
if (index > 0)
{
bool lIsSelected = !Pieza.Superficies.Where(x=>x.Id == index).First().IsSelected;
Pieza.Superficies.Where(x => x.Id == index).First().IsSelected = lIsSelected;
if (lIsSelected)
myShape.Fill = new SolidColorBrush(SystemColors.HotTrackColor);
else
myShape.Fill = new SolidColorBrush(SystemColors.ControlLightLightColor);
}
}
How can I do to cast it ?
The most straightforward way is
index = int.Parse(lcNombre);
If you're not completely sure whether lcNombre is really an integer, you can use instead
int result;
bool isInt = int.TryParse(lcNobre, out result);
or in newer versions of .NET, you can declare the output variable like:
bool isInt = int.TryParse(lcNobre, out var result);
Finally you can use
index = Convert.ToInt32(lcNobre);
This approach (like int.Parse()) will throw a FormatException if the input value is not convertible to an integer.
You can also use the Convert static methods:
index = Convert.ToInt32(lcNombre);
MSDN Link: http://msdn.microsoft.com/en-us/library/sf1aw27b(v=vs.110).aspx
Error wise.. you may want to use TryParse.. as it returns true or false depending on a successful conversion:
int index;
if (int.TryParse(lcNombre, out index)) {
// conversion successful
}
else {
// couldn't convert
}
MSDN Link for int.TryParse: http://msdn.microsoft.com/en-us/library/f02979c7(v=vs.110).aspx
try this
int result=0;
Int32.TryParse(lcNombre,out result);
My favorite way to do this is to make an extension method as follows
public static class ExtensionMethods
{
public static int? AsInteger( this string str)
{
int value;
if ( int.TryParse( str, out value ) )
{
return value;
}
else
{
return null;
}
}
}
then you can this
index = lcNombre.AsInteger() ?? 0;
string strArr[] = myShape.Name.Split('_',StringSplitOptions.RemoveEmptyEntries)
int num;
int.TryParse(strArr[0],num);
Related
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 { }
Is there any possible way to make this code shorter?
int? index = ListOfPeople.BinarySearch(searchBar.Text);
int? temp = int.TryParse(index.ToString(), out int i) ? (int?)1 : null;
MyPeopleGrid.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect;
MyPeopleGrid.Rows[i].Selected = true;
MyPeopleGrid.CurrentCell = MyPeopleGrid.Rows[i].Cells[0];
You seem to have seriously overcomplicated things, and you certainly should never convert a number to a string only to parse it back to a number.
int index = ListOfPeople.BinarySearch(searchBar.Text);
This will return a non-negative number when the item isn't found. It does not return int?, it returns int.
So now you can use it:
int index = ListOfPeople.BinarySearch(searchBar.Text);
if (index >= 0)
{
MyPeopleGrid.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect;
MyPeopleGrid.Rows[index].Selected = true;
MyPeopleGrid.CurrentCell = MyPeopleGrid.Rows[index].Cells[0];
}
else
{
// do something when the item isn't found
}
I have the following code:
static void Main(string[] args)
{
string prueba = "Something_2.zip";
int num;
prueba = prueba.Split('.')[0];
if (!prueba.Contains("_"))
{
prueba = prueba + "_";
}
else
{
//The code I want to try
}
}
The idea is that in the else I want to split the string after the _ and convert it to int, I did this like
num = Convert.ToInt16(prueba.Split('_')[1]);
but can I cast the split? for example num = (int)(prueba.Split('_')[1]);
Is it possible to do it that way? Or I have to use the Convert?
You Cannot cast string as integer, so you need to do some conversion:
I suggest you to use Int.TryParse() in this scenario.
Hence the else part will be like the following:
else
{
if(int.TryParse(prueba.Substring(prueba.LastIndexOf('_')),out num))
{
//proceed your code
}
else
{
//Throw error message
}
}
Convert the string to int like this:
var myInt = 0;
if (Int32.TryParse(prueba.Split('_')[1], out myInt))
{
// use myInt here
}
It's a string, so you'll have to parse it. You can use Convert.ToInt32, int.Parse, or int.TryParse to do so, like so:
var numString = prueba.Split('_')[1];
var numByConvert = Convert.ToInt32(numString);
var numByParse = int.Parse(numString);
int numByTryParse;
if(int.TryParse(numString, out numByTryParse))
{/*Success, numByTryParse is populated with the numString's int value.*/}
else
{/*Failure. You can handle the fact that it failed to parse now. numByTryParse will be 0 */}
string prueba = "Something_2.zip";
prueba = prueba.Split('.')[0];
int theValue = 0; // Also default value if no '_' is found
var index = prueba.LastIndexOf('_');
if(index >= 0)
int.TryParse(prueba.Substring(index + 1), out theValue);
theValue.Dump();
You could use a regular expression and avoid all the string splitting logic. If you need an explanation of the regex I've used see https://regex101.com/r/fW9fX5/1
var num = -1; // set to default value that you intend to use when the string doesn't contain an underscore
var fileNamePattern = new Regex(#".*_(?<num>\d+)\..*");
var regexMatch = fileNamePattern.Match("Something_2.zip");
if (regexMatch.Success)
{
int.TryParse(regexMatch.Groups["num"].Value, out num);
}
Say I have int val = 1; What is the best way to check whether or not that value corresponds with an enum. Here is a sample enum:
public enum AlertType
{
Success=1,
Warning=2,
Error=3
};
I'm looking for an answer that has the best maintainability.
I think you are looking for Enum::IsDefined Method
Returns an indication whether a constant with a specified value exists
in a specified enumeration.
Updated:-
Try something like this:-
if(Enum.IsDefined(typeof(AlertType), val)) {}
This should work:
Int32 val = 1;
if (Enum.GetValues(typeof(AlertType)).Cast<Int32>().Contains(val))
{
}
You can cast you enum choices to an int for that check :
const int val = 1;
if (val == (int)AlertType.Success)
{
// Do stuff
}
else if (val == (int) AlertType.Warning)
{
// Do stuff
}
else if (val == (int) AlertType.Error)
{
// Do stuff
}
In addition to the other solutions offered, here's another easy way to check:
Enum.GetName(typeof(AlertType), (AlertType)val) != null
if (Enum.IsDefined(typeof(AlertType), x))
{
var enumVal = Enum.Parse(typeof(AlertType), x.ToString());
}
else
{
//Value not defined
}
In the stub below how do I pass in (MyEnum) as a parameter such that I can use this procedure with any enum?
public static Enum Proc(this Enum e)
{
Int32 i = (Int32)(MyEnum)e;
...
Here is the solution I have come up with that works:
public static Enum Next(this Enum e, Type eT)
{
Int32 i = (Int32)(Object)e;
return (Enum)Enum.Parse(eT, Enum.GetName(eT, Enum.GetName(eT, ++i) == null? i = 0 : i));
}
This solution isn't ideal because I have to do this to get the next value:
MyEnum e = (MyEnum)e.Next(typeof(MyEnum));
I'd rather just do
MyEnum e = e.Next(typeof(MyEnum));
Or even better:
MyEnum e = e.Next();
Anyone who can provide the simple solution can have the point.
Also the code I've written above runs fine in LinqPad but only compiles in WP7 and then throws an exception when I run it (InvalidProgramException).
Here's a function that will cycle through the values of any enum:
static public Enum Cycle(this Enum e)
{
bool found = false;
Enum first = null;
foreach (Enum i in Enum.GetValues(e.GetType()))
{
if (first == null)
first = i;
if (found)
return i;
found = e.Equals(i);
}
if (found)
return first;
return null;
}
For versions of C# that don't have Enum.GetValues, you'll have to use a method like this which only works for enums whose values start at 0 and increment by 1:
static public Enum Cycle(this Enum e)
{
var i = ((IConvertible)e).ToInt64(null) + 1;
var eT = e.GetType();
var next = Enum.GetName(eT, i);
return (Enum)Enum.Parse(eT, next ?? Enum.GetName(eT, 0), false);
}
Use it like:
var nextEnum = (MyEnum)curEnum.Cycle();
Edit: I updated this to return the next enum in the list, strongly typed, regardless of what the numbering of the enum values may be. I'm able to compile and run this under .NET 4 and haven't tried it on WP7, but I don't think I'm using anything that's missing/disabled in SL/WP7.
public static T Next<T>(this T e) where T : struct
{
var t = typeof(T);
if (!t.IsEnum) throw new ArgumentException("T must be an enumerated type");
if (!Enum.IsDefined(t, e)) throw new ArgumentException();
var intValue = (int)t.GetField(e.ToString()).GetValue(null);
var enumValues = t.GetFields(BindingFlags.Public | BindingFlags.Static).Select(x => x.GetValue(null));
var next = (T?)enumValues.Where(x => (int)x > intValue).Min();
if (next.HasValue)
return next.Value;
else
return (T)enumValues.Min();
}
It can be used as simply as:
var nextE = e.Next();