java nullable,Nullable类型作为通用参数可能吗?

回答(10)

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

将返回类型更改为Nullable,并使用非可空参数调用该方法

static void Main(string[] args)

{

int? i = GetValueOrNull(null, string.Empty);

}

public static Nullable GetValueOrNull(DbDataRecord reader, string columnName) where T : struct

{

object columnValue = reader[columnName];

if (!(columnValue is DBNull))

return (T)columnValue;

return null;

}

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

public static T GetValueOrDefault(this IDataRecord rdr, int index)

{

object val = rdr[index];

if (!(val is DBNull))

return (T)val;

return default(T);

}

只需使用它:

decimal? Quantity = rdr.GetValueOrDefault(1);

string Unit = rdr.GetValueOrDefault(2);

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

只需对原始代码执行两项操作 - 删除 where 约束,并将最后一个 return 从 return null 更改为 return default(T) . 这样你就可以返回你想要的任何类型 .

顺便说一句,您可以通过将 if 语句更改为 if (columnValue != DBNull.Value) 来避免使用 is .

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

只需做一些与此类似的令人难以置信的事情 . 我的代码:

public T IsNull(this object value, T nullAlterative)

{

if(value != DBNull.Value)

{

Type type = typeof(T);

if (type.IsGenericType &&

type.GetGenericTypeDefinition() == typeof(Nullable<>).GetGenericTypeDefinition())

{

type = Nullable.GetUnderlyingType(type);

}

return (T)(type.IsEnum ? Enum.ToObject(type, Convert.ToInt32(value)) :

Convert.ChangeType(value, type));

}

else

return nullAlternative;

}

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

Disclaimer: 此答案有效,但仅用于教育目的 . :)詹姆斯琼斯' solution is probably the best here and certainly the one I'去吧 .

如果不太安全,C#4.0的 dynamic 关键字会让这更容易:

public static dynamic GetNullableValue(this IDataRecord record, string columnName)

{

var val = reader[columnName];

return (val == DBNull.Value ? null : val);

}

现在,您不需要在RHS上显式类型提示:

int? value = myDataReader.GetNullableValue("MyColumnName");

事实上,你根本不需要它!

var value = myDataReader.GetNullableValue("MyColumnName");

value 现在将是一个int,或一个字符串,或从DB返回的任何类型 .

唯一的问题是,这并不妨碍您在LHS上使用不可为空的类型,在这种情况下,您将获得一个相当讨厌的运行时异常,如:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot convert null to 'int' because it is a non-nullable value type

与使用 dynamic 的所有代码一样:告诫编码器 .

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

我想你想要处理引用类型和结构类型 . 我用它将XML Element字符串转换为更类型的字符串 . 您可以使用反射删除nullAlternative . formatprovider用于处理依赖于文化的' . '或','分隔符,例如小数或整数和双精度数 . 这可能有效:

public T GetValueOrNull(string strElementNameToSearchFor, IFormatProvider provider = null )

{

IFormatProvider theProvider = provider == null ? Provider : provider;

XElement elm = GetUniqueXElement(strElementNameToSearchFor);

if (elm == null)

{

object o = Activator.CreateInstance(typeof(T));

return (T)o;

}

else

{

try

{

Type type = typeof(T);

if (type.IsGenericType &&

type.GetGenericTypeDefinition() == typeof(Nullable<>).GetGenericTypeDefinition())

{

type = Nullable.GetUnderlyingType(type);

}

return (T)Convert.ChangeType(elm.Value, type, theProvider);

}

catch (Exception)

{

object o = Activator.CreateInstance(typeof(T));

return (T)o;

}

}

}

你可以像这样使用它:

iRes = helper.GetValueOrNull("top_overrun_length");

Assert.AreEqual(100, iRes);

decimal? dRes = helper.GetValueOrNull("top_overrun_bend_degrees");

Assert.AreEqual(new Decimal(10.1), dRes);

String strRes = helper.GetValueOrNull("top_overrun_bend_degrees");

Assert.AreEqual("10.1", strRes);

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

这可能是一个死线程,但我倾向于使用以下内容:

public static T? GetValueOrNull(this DbDataRecord reader, string columnName)

where T : struct

{

return reader[columnName] as T?;

}

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

我自己也遇到了同样的问题 .

... = reader["myYear"] as int?; 工作,很干净 .

它适用于任何类型,没有问题 . 如果结果是DBNull,则在转换失败时返回null .

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

我知道这是旧的,但这是另一种解决方案:

public static bool GetValueOrDefault(this SqlDataReader Reader, string ColumnName, out T Result)

{

try

{

object ColumnValue = Reader[ColumnName];

Result = (ColumnValue!=null && ColumnValue != DBNull.Value) ? (T)ColumnValue : default(T);

return ColumnValue!=null && ColumnValue != DBNull.Value;

}

catch

{

// Possibly an invalid cast?

return false;

}

}

现在,您不关心 T 是值还是引用类型 . 仅当函数返回true时,您才能从数据库中获得合理的值 . 用法:

...

decimal Quantity;

if (rdr.GetValueOrDefault("YourColumnName", out Quantity))

{

// Do something with Quantity

}

这种方法与 int.TryParse("123", out MyInt); 非常相似

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

多个通用约束不能以OR方式组合(限制性较小),仅以AND方式(更具限制性)组合 . 意味着一种方法无法处理这两种情况 . 通用约束也不能用于为方法创建唯一的签名,因此您必须使用2个单独的方法名称 .

但是,您可以使用通用约束来确保正确使用方法 .

在我的例子中,我特别希望返回null,而不是任何可能的值类型的默认值 . GetValueOrDefault =坏 . GetValueOrNull =好 .

我使用“Null”和“Nullable”这两个词来区分引用类型和值类型 . 这里是我编写的一些扩展方法的示例,它们补充了System.Linq.Enumerable类中的FirstOrDefault方法 .

public static TSource FirstOrNull(this IEnumerable source)

where TSource: class

{

if (source == null) return null;

var result = source.FirstOrDefault(); // Default for a class is null

return result;

}

public static TSource? FirstOrNullable(this IEnumerable source)

where TSource : struct

{

if (source == null) return null;

var result = source.FirstOrDefault(); // Default for a nullable is null

return result;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值