Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

More elegant way of finding out if I can convert a value into a certain type

I'm working with some legacy code right now which usually used try + catch in combination with Convert.ToDecimal(someString) (for instance) to try and convert strings to decimals. For some reasons I have to use the setting that - when debugging - I stop at every thrown exception (not only user-unhandled ones) and so this got annoying and I changed it to use TryParse methods whenever possible.

Now I'm in a situation where there's an object value and a target Type, and all I want to know is if I can convert the value into the target type. Right now this is done as follows:

try
{
  Convert.ChangeType(val, targetType);
}
catch
{
  // Do something else
}

The actual result is not important and is not used further.

While this code is working right now, as I said, it gets a bit annoying and so I wonder: Is there another way of doing the above without having to catch an exception?

I thought of something like IsAssignableFrom on a Type, but this doesn't seem to be applicable in my case (I don't want to assign, I want to know if explicitly converting is possible).

like image 480
InvisiblePanda Avatar asked Nov 11 '15 07:11

InvisiblePanda


2 Answers

I'll give you a solution to "hide" exceptions. Sometimes it's neccessary to catch an exception and as you said it's annoying because the debugger will stop on every exception. I know that, but there is a way of doing that:

[DebuggerStepThrough]
public bool CanChangeType(this object instance, Type targetType)
{
  try
  {
    Convert.ChangeType(val, targetType);
    return true;
  }
  catch
  {
    return false;
  }
}

The trick is the DebuggerStepThrough-attribute.

But keep in mind that you'll never be able to debug into such a method. There is no bugfixing without removing the attribute. Knowing that a method should be short - very short and should obviously be free of all errors.

I'm having the same problems with Udp-classes that throw an exception on close. Extracting this short code to a separate method that contains no error works fine.

like image 36
Sebastian Schumann Avatar answered Oct 24 '22 06:10

Sebastian Schumann


If you mean casting, than you can use is keyword like:

object someObject = GetSomeObject();
if (someObject is string)
{
    ..
}

But note, that casting and Convert.ChangeType are not the same. For example, you can not cast a string to an int:

string numberString = "15";
int number = (int)numberString;

but you can use ChangeType for it:

string numberString = "15";
int number = (int)Convert.ChangeType(numberString, typeof(int));

EDIT:

If you need to test a variable for being convertible to specific type, then why not just wrap try-catch with Convert.ChangeType into a test method:

public bool IsConvertibleTo<T>(object value)
{
    try 
    {
        T convertedValue = (T)Convert.ChangeType(value, typeof(T));
        return true;
    }
    catch (InvalidCastException)
    {
        return false;
    }
    catch (FormatException)
    {
        return false;
    }
    catch (OverflowException)
    {
        return false;
    }
}
like image 122
Dmitry Savchenko Avatar answered Oct 24 '22 06:10

Dmitry Savchenko