简体   繁体   中英

C# bool value as string is always null

I'm attempting to dump variable property information to a simple string but when it gets to my nullable bools, the as string always returns null --even if the actual value is true | false!

StringBuilder propertyDump = new StringBuilder();

foreach(PropertyInfo property in typeof(MyClass).GetProperties())
{
    propertyDump.Append(property.Name)
                .Append(":")
                .Append(property.GetValue(myClassInstance, null) as string);
}

return propertyDump.ToString();

No exceptions are thrown; quick and the output is exactly what I want except any properties that are bool? are always false. If I quick watch and do .ToString() it works! But I can't guarantee other properties are not, in fact, null.

Can anyone explain why this is? and even better, a workaround?

A bool is not a string, so the as operator returns null when you pass it a boxed boolean.

In your case, you could use something like:

object value = property.GetValue(myClassInstance, null);

propertyDump.Append(property.Name)
            .Append(":")
            .Append(value == null ? "null" : value.ToString());

If you want to have null values just not append any text, you can just use Append(Object) directly:

propertyDump.Append(property.Name)
            .Append(":")
            .Append(property.GetValue(myClassInstance, null));

This will work, but leave null properties in your "propertyDump" output as missing entries.

The as operator returns a casted value if the instance is of that exact type, or null otherwise.

Instead, you just should .Append(property.GetValue(...)) ; Append() will automatically handle nulls and conversions.

The nicest solution would be, in my opinion:

.Append(property.GetValue(myClassInstance, null) ?? "null");

If the value is null, it will append "null", and if not - it will call the value's ToString and append that.

Combining that with Linq instead of a foreach loop, you can have a nice little something:

var propertyDump =
    string.Join(Environment.NewLine,
                typeof(myClass).GetProperties().Select(
                    pi => string.Format("{0}: {1}",
                                        pi.Name,
                                        pi.GetValue(myClassInstance, null) ?? "null")));

(Looks nicer in the wide screen of VS).

If you compare speeds, by the way, it turns out the string.Join is faster than Appending to a StringBuilder, so I thought you might want to see this solution.

That's because the type of the property is not string. Change it to:

Convert.ToString(property.GetValue(myClassInstance, null))

If it's null, it will retrieve null and that's ok. For non-null values it will return the string representation of the value of the property.

You cannot cast a bool to a string. You must use ToString()

Use the null coalesing operator to handle the Null situations:

void Main()
{

   TestIt tbTrue = new TestIt() { BValue = true }; // Comment out assignment to see null

   var result =
    tbTrue.GetType()
          .GetProperties()
          .FirstOrDefault( prp => prp.Name == "BValue" )
          .GetValue( tb, null ) ?? false.ToString();

      Console.WriteLine ( result ); // True

}

public class TestIt
{
   public bool? BValue { get; set; }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM