【问题标题】:Generic method to return Nullable Type values返回 Nullable 类型值的通用方法
【发布时间】:2013-06-28 11:43:07
【问题描述】:

我写了下面的方法,满足以下要求-

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

    3.1。对于 int -1 3.2.对于日期时间 DateTime.MinValue 3.3.对于字符串,空 3.4.对于布尔值,null

对于案例 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

期待一些帮助。

【问题讨论】:

  • 如何调用第一组代码中的方法?您需要将其称为AttributeValue&lt;bool?&gt;(...) 如果您只调用AttributeValue&lt;bool&gt;(...),那么null 不是bool 的有效值。编辑:您的第二种情况失败,因为string 不能用于System.Nullable&lt;T&gt;,因为string 不是值类型结构。

标签: c# nullable generic-programming


【解决方案1】:

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

然后您可以将default 关键字用于 3.3 和 3.4(字符串和布尔值?)。根据msdn,它将为引用类型返回null,为值类型(如int或bool)返回默认值。

你可以像这样使用它

return default(T);

【讨论】:

  • bool case (3.4) 的要求是它返回null。这将返回 false 而不是与未找到匹配属性的情况和提供“false”的情况进行区分。
  • 您不需要使用它然后将bool? 作为通用参数,在这种情况下返回 null 吗?我的意思是,如果 T 是 bool 你不能返回 false,所以你需要使用 bool?...
  • 澄清一下,bool? 的 default(T) 将返回 null
  • 啊,当然。也许只是在你的答案中指定。我在想它会被用来对付bool,而不是bool?。你完全正确。
【解决方案2】:

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

它为类型返回 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");

它对我很有效。谢谢大家...

【讨论】:

  • 我现在可以返回空值了。这看起来是一个更好的解决方案,
【解决方案3】:

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

您的第二个代码块失败,因为您不能将string 用于Nullable&lt;T&gt; 的泛型类型,因为它需要一个值类型struct,而string 是一个引用类型类。

您需要更改第一个方法块以查找 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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-23
    • 2020-10-03
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 2012-04-06
    • 2010-10-01
    相关资源
    最近更新 更多