3
\$\begingroup\$

At the moment I am using this to check a boolean property in sharepoint 2007 using C# and .Net Framework 3.5

if (bool.Parse(listItem.Properties["Boolean Property"].ToString()) == false)

is there any better way of doing it ?

Edit

when my code try to convert property into string it gives me exception even when am validating if property is empty or not.

This Worked For me

using method "Contains Key" instead of "Properties.Containsfield"

object abc = "bool property";

foreach (SPListItem item in list.Items)
{
     if (item.Properties.ContainsKey(abc)
\$\endgroup\$
  • \$\begingroup\$ I explained some of the errors that your approach is likely to generate in my answer. My guess is it's either a NullReferenceException or a FormatException \$\endgroup\$ – smartcaveman Oct 9 '12 at 13:02
  • \$\begingroup\$ Unrelated, but note that use of boolean literals in comparisons is something that I’d flag in every code review. Boolean literals have one use, and one use only: to initialise a boolean value. \$\endgroup\$ – Konrad Rudolph Oct 9 '12 at 16:44
8
\$\begingroup\$

I am making some assumptions about your code, specifically that listItem is of type SPListItem and that listItem.Properties is a HashTable. This is mainly to provide context for my explanation, but even if I am mistaken, most of my comments will still hold. For the sake of context, let's assume your actual method looks like:

 void HandleBooleanListItemProperty( SPListItem listItem ){ 
    if (bool.Parse(listItem.Properties["Boolean Property"].ToString()) == false){ 
        // do something if the Boolean ListItem property is false
    } 
    else
    { 
        // do something if the Boolean ListItem property is true
    }
} 
  1. Validate that the object exists before you call ToString(). The way your method is currently written, you will get a NullReferenceException if the key "Boolean Property" is missing or the hashed value that corresponds to the "Boolean Property" key is null. This refactoring will make the method look like:

    void HandleBooleanListItemProperty2( SPListItem listItem ){ 
         object booleanPropertyValue = listItem.Properties["Boolean Property"];
         if ( ReferenceEquals( booleanPropertyValue, null ) ) {
             // do something if the Boolean ListItem property is missing
         } 
         else if (bool.Parse(booleanPropertyValue.ToString()) == false){ 
             // do something if the Boolean ListItem property is false
         } 
         else { 
             // do something if the Boolean ListItem property is true
         }
     } 
    
  2. Use bool.TryParse instead of bool.Parse. If the ToString() value of the hashed value corresponding to the key "Boolean Property" is anything other than "true" or "false" (case-insensitive), a FormatException will be thrown. This refactoring will make the method look like:

     void HandleBooleanListItemProperty3( SPListItem listItem ){ 
         object booleanPropertyValue = listItem.Properties["Boolean Property"];
         bool parsedBooleanPropertyValue;
         if ( ReferenceEquals( booleanPropertyValue, null ) ) { 
             // do something if the Boolean ListItem property is missing
         }
         else if (bool.TryParse(booleanPropertyValue.ToString(), out parsedBooleanPropertyValue) ) 
         {
             if(parsedBooleanPropertyValue == false){ 
                // do something if the Boolean ListItem property is false
             }
             else { 
               // do something if the Boolean ListItem property is true
             }
         } 
         else { 
              // do something if the Boolean ListItem property's ToString() value was something other than "true" or "false"
         }
     }  
    
  3. If the hashed value that corresponds to the "Boolean Property" key is really a bool, then cast it before comparing. Calling ToString() just throws away .NET's type-safety. This refactoring will make the method look like:

     void HandleBooleanListItemProperty4( SPListItem listItem ){ 
         object booleanPropertyValue = listItem.Properties["Boolean Property"];
         if (booleanPropertyValue is bool) 
         {
            bool castBooleanPropertyValue = (bool) booleanPropertyValue;
             if( castBooleanPropertyValue == false ){ 
                // do something if the Boolean ListItem property is false
             }
             else { 
               // do something if the Boolean ListItem property is true
             }
         } 
         else { 
             // do something if the Boolean ListItem property is not a bool        
             if ( ReferenceEquals( booleanPropertyValue, null ) ) { 
                 // do something if the Boolean ListItem property is missing
             }
             else {
                 // do something if the Boolean ListItem property is something other than a bool
             }
         }
     } 
    
  4. Eliminate magic strings from your value accessor. This requires removing the inline "Boolean Property" and declaring with that value, and then using the constant in order to access the value in every usage. This decreases the possibility that a typos will cause bugs. An article on magic strings is available at: http://codebetter.com/matthewpodwysocki/2009/03/19/functional-net-lose-the-magic-strings/ . The resulting refactoring would look like:

     const string BooleanPropertyKey = "Boolean Property";
    
     void HandleBooleanListItemProperty5( SPListItem listItem ){ 
         object booleanPropertyValue = listItem.Properties[BooleanPropertyKey];
         if (booleanPropertyValue is bool) 
         {
            bool castBooleanPropertyValue = (bool) booleanPropertyValue;
             if( castBooleanPropertyValue == false ){ 
                // do something if the Boolean ListItem property is false
             }
             else { 
               // do something if the Boolean ListItem property is true
             }
         } 
         else { 
             // do something if the Boolean ListItem property is not a bool        
             if ( ReferenceEquals( booleanPropertyValue, null ) ) { 
                 // do something if the Boolean ListItem property is missing
             }
             else {
                 // do something if the Boolean ListItem property is something other than a bool
             }
         }
     } 
    
  5. Use the negation operator (!) instead of comparing to false. This is much more readable and will save you time in the long run. This final refactoring looks like:

     const string BooleanPropertyKey = "Boolean Property";
    
     void HandleBooleanListItemProperty6( SPListItem listItem ){ 
         object booleanPropertyValue = listItem.Properties[BooleanPropertyKey];
         if (booleanPropertyValue is bool) 
         {
            bool castBooleanPropertyValue = (bool) booleanPropertyValue;
             if( !castBooleanPropertyValue ){ 
                // do something if the Boolean ListItem property is false
             }
             else { 
               // do something if the Boolean ListItem property is true
             }
         } 
         else { 
             // do something if the Boolean ListItem property is not a bool        
             if ( ReferenceEquals( booleanPropertyValue, null ) ) { 
                 // do something if the Boolean ListItem property is missing
             }
             else {
                 // do something if the Boolean ListItem property is something other than a bool
             }
         }
     } 
    
\$\endgroup\$
  • \$\begingroup\$ thanks for explaining it in details and I did tried number 5, but when property is there it isn't going to first if statement but going to else statement and I just debugged and looked at what property is returned as and its returned as "1" for that particular item and code thinks its not boolean \$\endgroup\$ – Muhammad Raja Oct 9 '12 at 13:24
  • 1
    \$\begingroup\$ @TimeToThine, I guess you are used to working with JavaScript, huh? In C#, 1 is not a Boolean. It is an integer. You can use the same approach with int instead of bool, and then check if( ((int)listItem.Properties[BooleanPropertyKey]) == 1 ) \$\endgroup\$ – smartcaveman Oct 9 '12 at 13:31
  • \$\begingroup\$ sorry am bit confused now, I looked at XML returned by SharePoint in my solution while its attached to list and in XML it got "1" as value for that property but when I tried to get values of all items using console app, its giving me as true, however for one item I am getting "object not set to reference" for which I think has been already added before custom property wasn't added to list. \$\endgroup\$ – Muhammad Raja Oct 9 '12 at 13:36
  • \$\begingroup\$ XML stores a boolean value as a 1. This is different than the C# literal 1. If you are deserializing the XML document to a HashTable, it should be converted to a Boolean. Your problem is that there is no value in the HashTable with the key "Boolean Property", so when you ask the HashTable for it, it gives you null. When you ask null for ToString(), it gives you a NullReferenceException ("Object not set to a reference") \$\endgroup\$ – smartcaveman Oct 9 '12 at 13:39
  • \$\begingroup\$ thats true, I think I want to catch this this null exception in a way that I can do something with it without throwing any exception, just like you explained it in code above, but number 5 isn't working like it should be :( \$\endgroup\$ – Muhammad Raja Oct 9 '12 at 13:43
4
\$\begingroup\$

The .Parse methods will throw exceptions if the value is null, in a bad format, etc.

I suggest always using the .TryParse methods instead:

bool val;
if(!bool.TryParse(listItem.Properties["Boolean Property"].ToString(), out foo)) {
    val = false;
}

Or perhaps one of the Convert.ToBoolean() methods.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.