InvisiblePanda
InvisiblePanda

Reputation: 1609

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).

Upvotes: 6

Views: 1182

Answers (4)

Dbl
Dbl

Reputation: 5894

Your initial guess is right.

    public static bool CanChangeType(Type type)
    {
        return typeof (IConvertible).IsAssignableFrom(type);
    }

is the right way to check by type whether Convert.ChangeType will work or not (as the exception message usually indicates). Not sure why you're opposed to this method because of the "Assign" in it's name. It's just performing some checking on the type. Other than that it doesn't actually do any assigning.

Upvotes: -1

Sebastian Schumann
Sebastian Schumann

Reputation: 3446

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.

Upvotes: 2

Dzmitry Sauchanka
Dzmitry Sauchanka

Reputation: 412

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;
    }
}

Upvotes: 4

Itachi
Itachi

Reputation: 6070

If you want to check the type of val, you should use keyword is like this,

if (val is targetType) {
    ...
}

If you want to convert val to type targetType, you should use keyword as like this,

targetType result = val as targetType;

if (result != null) {
    ...
}

Both of them won't throw an exception out!

Link: https://msdn.microsoft.com/zh-cn/library/cscsdfbt.aspx

Upvotes: 0

Related Questions