General method for returning Nullable Type values

I wrote below a method requiring it to be -

  • input is xmlnode and attributeName
  • returns the value if it is found with the passed attribute name
  • If the passed attribute does not have a value, it should return -

    3.1. For int -1 3.2. For Datetime DateTime.MinValue 3.3. For String, null 3.4. For bool, null

The method below does not hold for case 3.4.

public T AttributeValue<T>(XmlNode node, string attributeName) { var value = new object(); if (node.Attributes[attributeName] != null && !string.IsNullOrEmpty(node.Attributes[attributeName].Value)) { value = node.Attributes[attributeName].Value; } else { if (typeof(T) == typeof(int)) value = -1; else if (typeof(T) == typeof(DateTime)) value = DateTime.MinValue; else if (typeof(T) == typeof(string)) value = null; else if (typeof(T) == typeof(bool)) value = null; } return (T)Convert.ChangeType(value, typeof(T)); } 

When changing this value to

 public System.Nullable<T> AttributeValue<T>(XmlNode node, string attributeName) where T : struct { var value = new object(); if (node.Attributes[attributeName] != null && !string.IsNullOrEmpty(node.Attributes[attributeName].Value)) { value = node.Attributes[attributeName].Value; } else { if (typeof(T) == typeof(int)) value = -1; else if (typeof(T) == typeof(DateTime)) value = DateTime.MinValue; else if (typeof(T) == typeof(string)) return null; else if (typeof(T) == typeof(bool)) return null; } return (T?)Convert.ChangeType(value, typeof(T)); } 

Error for string type, i.e. case 3.3

Looking forward to some help.

+6
source share
3 answers

thanks for the number of answers, here is what I wrote and works for me ..

It returns null for types.

 public T AttributeValue<T>(XmlNode node, string attributeName) { object value = null; if (node.Attributes[attributeName] != null && !string.IsNullOrEmpty(node.Attributes[attributeName].Value)) value = node.Attributes[attributeName].Value; if (typeof(T) == typeof(bool?) && value != null) value = (string.Compare(value.ToString(), "1", true) == 0).ToString(); var t = typeof(T); t = Nullable.GetUnderlyingType(t) ?? t; return (value == null) ? default(T) : (T)Convert.ChangeType(value, t); } 

I call it that

  const string auditData = "<mydata><data><equipmentStatiticsData><userStatistics maxUsers='100' totalUsers='1' authUsers='0' pendingUsers='' adminAddedUsers='' xmlUsers='' internalDBUsers='' webUsers='' macUsers='' vpnUsers='' xUsers8021=''></userStatistics><equipmentStatistics cpuUseNow='14' cpuUse5Sec='1' cpuUse10Sec='1' cpuUse20Sec='1' ramTotal='31301632' ramUtilization ='1896448' ramBuffer='774144' ramCached='8269824' permStorageUse='24' tempStorageUse='24'></equipmentStatistics><authStatus status='1'></authStatus></equipmentStatiticsData></data></mydata>"; xmlDoc.LoadXml(auditData); var userStatsNode = xmlDoc.SelectSingleNode("/mydata/data/equipmentStatiticsData/userStatistics"); var intNullable = AttributeValue<int?>(userStatsNode, "vpnUsers"); var nullableBoolTrue = AttributeValue<bool?>(userStatsNode, "totalUsers"); var nullableBoolFalse = AttributeValue<bool?>(userStatsNode, "authUsers"); var nullableString = AttributeValue<string>(userStatsNode, "authUsers"); var pendingUsersBoolNull = AttributeValue<bool?>(userStatsNode, "pendingUsers"); var testAttribNullableNotFoundDateTime = AttributeValue<DateTime?>(userStatsNode, "testAttrib"); var testAttrib1NullString = AttributeValue<string>(userStatsNode, "testAttrib"); var maxUsersNullInt = AttributeValue<int?>(userStatsNode, "maxUsers"); 

It works well for me. thanks to the people ...

+4
source

For 3.4 do you need to use bool? as a type for T so you can return null.

Then you can use the default keyword for 3.3 and 3.4 (string and bool?). By msdn, it will return null for reference types and default values ​​for value types (e.g. int or bool).

You can use it as

 return default(T); 
+5
source

Need to call your first code with bool? not bool because null not a valid value for a non-nullable bool .

The second code block does not work because you cannot use string for the general type Nullable<T> , since it requires a value type of struct and string .

You will need to change your first method block to look for typeof(bool?) And call it using a type with a zero Boolean type:

 public T AttributeValue<T>(XmlNode node, string attributeName) { var value = new object(); if (node.Attributes[attributeName] != null && !string.IsNullOrEmpty(node.Attributes[attributeName].Value)) { value = node.Attributes[attributeName].Value; } else { if (typeof(T) == typeof(int)) value = -1; else if (typeof(T) == typeof(DateTime)) value = DateTime.MinValue; else if (typeof(T) == typeof(string)) value = null; else if (typeof(T) == typeof(bool?)) value = null; } var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T); return (T)Convert.ChangeType(value, type); } 

Then name it like:

 bool? value = AttributeValue<bool?>(node, "myAttributeName"); 

You also need to do a check since Convert.ChangeType will not work for a type with a null value. A quick fix from here resolves this. (it is included in the code above)

EDIT: here's the improved / cleaned version of your method:

 public T AttributeValue<T>(XmlNode node, string attributeName) { if (node.Attributes[attributeName] != null && !string.IsNullOrEmpty(node.Attributes[attributeName].Value)) { var value = node.Attributes[attributeName].Value; var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T); return (T)Convert.ChangeType(value, type); } else { if (typeof(T) == typeof(int)) return (T)(object)(-1); return default(T); } } 

You can add additional special cases for nonexistent nodes, but all your cases except int are already the default value for types, so just use default(T) .

0
source

Source: https://habr.com/ru/post/948316/


All Articles