(int)value
is causing exceptions because sometimes value is not an int. I want this code to handle values of multiple types, and cast to an int if possible so I can check what that int's value is (for example, casting an Enum to an int).
checking for value as int == null
doesn't work because int isn't a nullable type.
checking for value is int
doesn't appear to do the same thing; an Enum will return false even though it can be converted.
Int32.TryParse()
doesn't work because the source value must be a string.
I even tried typeof(int).IsAssignableFrom(value.GetType())
but that fails, presumably because it needs an explicit rather than implicit cast.
my best guess is to simply do a try-catch for the cast, but that's also awkward since I want to handle the lack of an exception (if value can be cast into int, do thing), not the exception. since the function just exits after this check I can just put a return in the catch and assume anything after the return can be cast to an int, but yeah that seems pretty hacky and not a great general-purpose solution. Any better ideas?
Edit: this question got closed for being a dupe of Better way to cast object to int
but 'a better way to cast' to int is not the same as checking if you can pre-cast.
the as int?
doesn't work because my test Enum still evaluates to null.
Convert.ToInt32()
doesn't work because it return 0 if the cast failed and the value if it succeeded, making it impossible to tell if it succeeded a cast to 0 or it failed.
OP's solution won't work, it'll evaluate the Enum to its name, not its int index.
Thankfully by thinking about it a tad more myself, I realized there's a pretty obvious solution.
bool canCastToInt(object o)
{
try
{
o = (int)o;
}
catch (Exception)
{
return false;
}
return true;
}
Tada.
I would write it using a "Try" syntax (like int.TryParse()
) like so:
public static bool TryCastToInt(object obj, out int result)
{
try
{
result = (int) obj;
return true;
}
catch
{
result = 0;
return false;
}
}
However, note that this cast will fail unless the object is an enum with underlying type int
or an actual int
. For example, it will fail for short
and double
.
If you want it to work for any type that can be explicitly cast to int
you can implement it using Convert.ChangeType()
like so:
public static bool TryCastToInt(object obj, out int result)
{
try
{
result = (int) Convert.ChangeType(obj, typeof(int));
return true;
}
catch
{
result = 0;
return false;
}
}
To see the difference, try the following console app:
namespace Console1;
public static class Program
{
enum ShortEnum: short { Item }
enum IntEnum { Item }
public static void Main()
{
test(1.234, "double");
test("x", "string");
test((short)1, "short");
test(ShortEnum.Item, "short enum");
test(IntEnum.Item, "int enum");
test(1, "int");
}
static void test(object obj, string name)
{
if (TryCastToInt(obj, out int value))
Console.WriteLine($"{name} = {value}");
else
Console.WriteLine($"Could not cast {name} to int.");
}
public static bool TryCastToInt(object obj, out int result)
{
try
{
// result = (int)obj;
result = (int) Convert.ChangeType(obj, typeof(int));
return true;
}
catch
{
result = 0;
return false;
}
}
}
Run this to see the results, and then comment out the ChangeType()
line and uncomment the (int)
line and run it again.