返回Nullable Type值的通用方法

时间:2013-06-28 11:43:08

标签: c# nullable generic-programming

  

我在下面的方法中写了以下要求 -

  1. 输入为xmlnode和attributeName
  2. 如果找到并传递了关联的属性名称
  3. ,则返回该值
  4. 如果传递的attributeName中没有值,则应返回 -

    3.1。对于int -1 3.2。对于Datetime DateTime.MinValue 3.3。对于String,null 3.4。对于bool,null

  5. 对于案例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));
            }
    

    将此更改为

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

    字符串类型失败,即案例3.3

    期待一些帮助。

3 个答案:

答案 0 :(得分:5)

对于3.4,您需要使用bool?作为T的类型,因此您可以返回null。

然后你可以使用default关键字3.3和3.4(string和bool?)。根据{{​​3}},它将为引用类型返回null,为值类型返回默认值(如int或bool)。

您可以像

一样使用它
return default(T);

答案 1 :(得分:4)

感谢您的回复,这是我写的,对我有用..

它为类型返回null。

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

我称之为

    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");

它适合我。谢谢人们......

答案 2 :(得分:0)

您需要使用bool?而不是bool来调用您的第一个代码集,因为null不是非可空bool的有效值。

您的第二个代码块失败,因为您无法将string用于Nullable<T>的泛型类型,因为它需要值类型structstring是参考-type class。

您需要更改第一个方法块以查找typeof(bool?)并使用可以为空的布尔类型调用它:

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

然后将其称为:

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

您还需要进行检查,因为Convert.ChangeType不适用于可空类型。来自here的快速解决方案可以解决问题。 (它包含在上面的代码中)

编辑:这是您的方法的改进/清理版本:

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

您可以为不存在的节点添加其他特殊情况,但除int之外的所有情况都已经是类型的默认值,因此只需使用default(T)