tags:

views:

320

answers:

5

I am getting a formatexception with the following code. Any one know how to make BooleanConverter convert from 0/1 to true/false.

 bool bVal=true;
 string sVal = "0";
 Console.WriteLine(TypeDescriptor.GetConverter(bVal).ConvertFrom(sVal));

Thanks for the help!

+2  A: 

There are only two cases so can just check for them explicitly.

Jared Updike
I am using a library that uses typeconverters for converting my strings... so if I pass 0/1 for a boolean field, i get this exception. I cannot control how it converts..
Gentoo
Can you give more information about what you have control over? can you ensure that the strings are properly "false" and "true"?
Jared Updike
I would convert the 0s and 1s to Ints or Strings internally (map the 0s and 1s to an int or string, don't try to map directly to a Bool) and then add a 'get' property that converts to Bool at runtime, returning the value you need in your code where you need it.
Jared Updike
hmm.. thats a nice idea. I am going to see if I can import it as an integer into my table and convert it to boolean on the fly as you say.Thanks again.
Gentoo
+3  A: 

Try the following

public static bool ConvertToBasedOnIntValue(string value) {
  // error checking omitted for brevity
  var i = Int32.Parse(value);
  return value == 0 ? false : true;
}

Or you could use the following which won't throw exceptions but it will consider everything that is quite literally not 0 to be true

public static bool ConvertToBasedOnIntValue(string value) {
  if ( 0 == StringComparer.CompareOrdinal(value, "0") ) {
    return false;
  }
  return true;
}
JaredPar
I was going to suggest exactly that so strings of non-zero map to true as in C.
Jared Updike
I am using linqtocsv library and in my csv file, i have a column with 0s and 1s. The field is marked as a nullable boolean (bool?) in my description. So when the library converts my csv file into the database, it does this field.TypeConverter.ConvertFromString(value). Value here is the "0" or "1" and TypeConverter becomes BooleanConverter and it throws me the FormatException. Thanks for the suggestion both of you. I am not sure if I can implement this in my case!
Gentoo
+1  A: 

If you're going to use Int32.Parse, use Int32.TryParse instead. It doesn't throw if the conversion fails, instead returning true or false. This means that it's more performant if all you're doing is checking to see if your input is a value. Example:

public static bool ConvertToBool(string value)
{
    int val = 0;
    return (int.TryParse(value, out val) && val == 0) ? false : true;
}

I have a tendency to go overboard on the ternary operator (x ? y : z), so here's a slightly easier-to-read version:

public static bool ConvertToBool(string value)
{
    int val = 0;
    if (int.TryParse(value, out val))
    {
        return val == 0 ? false : true;
    }

    return false;
}

(I tested them both. "1" returns true, "0" returns false.)

Ari Roth
A: 

I just built a helper function that will handle the special case of booleans:

    Private Shared Function StringConverter(ByVal colValue As String, ByVal propertyType As Type) As Object

    Dim returnValue As Object

    'Convert the string value to the correct type
    Select Case propertyType
        Case GetType(Boolean)
            'Booleans need to be coded separately because by default only "True" and "False" will map to a Boolean
            'value. SQL Server will export XML with Booleans set to "0" and "1". We want to handle these without
            'changing the xml.
            Select Case colValue
                Case "0"
                    returnValue = False
                Case "1"
                    returnValue = True
                Case "False"
                    returnValue = False
                Case "True"
                    returnValue = True
                Case Else
                    Throw New ArgumentException("Value of '" & colValue & "' cannot be converted to type Boolean.")
            End Select
        Case Else
            'Let .Net Framework handle the conversion for us
            returnValue = TypeDescriptor.GetConverter(propertyType).ConvertFromString(colValue)

    End Select

    Return returnValue

End Function
Patrick Cosyns
+1  A: 

Your original code was good enough, only you can't set the string value to "0" and "1". In your code, TypeConverter.ConvertFrom() will eventually invoke Boolean.TryParse(), the code for which looks like this (thanks Reflector!)

public static bool TryParse(string value, out bool result)
{
    result = false;
    if (value != null)
    {
        if ("True".Equals(value, StringComparison.OrdinalIgnoreCase))
        {
            result = true;
            return true;
        }
        if ("False".Equals(value, StringComparison.OrdinalIgnoreCase))
        {
            result = false;
            return true;
        }
        if (m_trimmableChars == null)
        {
            char[] destinationArray = new char[string.WhitespaceChars.Length + 1];
            Array.Copy(string.WhitespaceChars, destinationArray, string.WhitespaceChars.Length);
            destinationArray[destinationArray.Length - 1] = '\0';
            m_trimmableChars = destinationArray;
        }
        value = value.Trim(m_trimmableChars);
        if ("True".Equals(value, StringComparison.OrdinalIgnoreCase))
        {
            result = true;
            return true;
        }
        if ("False".Equals(value, StringComparison.OrdinalIgnoreCase))
        {
            result = false;
            return true;
        }
    }
    return false;
}

So make the following change to your code and you should be good:

bool bVal = true;
string sVal = "false";
Console.WriteLine(TypeDescriptor.GetConverter(bVal).ConvertFrom(sVal));
code4life