C#,Nullable十进制

Exp*_* be 2 c# asp.net

在我的数据库中,v1字段是可空字段.但如果值为null,我定义0(默认值).

public decimal? v1 {
  get {
    return this._v1; 
  }
  set {
    this._v1 = value ?? 0M;
  }
}
Run Code Online (Sandbox Code Playgroud)

所以现在,v1不再是可空变量了.

但我不能这样做,

decimal v2 = v1;
Run Code Online (Sandbox Code Playgroud)

错误信息说,不能隐式转换类型'decimal?' 到'十进制'.

在这种情况下,我是否必须转换为十进制,像这样?

decimal v2 = Convert.ToDecimal(v1);
Run Code Online (Sandbox Code Playgroud)

这是非常讨厌的工作.而且代码看起来也很脏.

谁知道更好的解决方案 请指教.

Jam*_*mes 14

不,您不必转换decimal?,您可以访问Nullable类型的基础值,例如

decimal v2 = v1.Value;
Run Code Online (Sandbox Code Playgroud)

Nullable类型分配默认值不会使其不可为空,它只是意味着它具有值.可空类型具有HasValue可帮助您确定此属性的属性.

只是为了记录在案,我不会推荐默认值,以0它可能会更有意义,让它默认为null考虑它可能确实是空的.如果您需要在应用程序中使用默认值,则可能需要使用该GetValueOrDefault方法,例如

decimal v2 = v1.GetValueOrDefault(0m);
Run Code Online (Sandbox Code Playgroud)


Mat*_*hew 5

将转换为decimal?decimal但将值设为0when 的最简单方法是null,您可以执行以下操作:

decimal? a = null;
decimal b = a.GetValueOrDefault(0m); // will contain 0 when null, otherwise the value
Run Code Online (Sandbox Code Playgroud)

阅读GetValueOrDefault

您也可以GetValueOrDefault不带任何参数调用,这将产生yield default(T),在Decimal的情况下为0,但我想明确指出。


Sin*_*tic 5

我很好奇为什么您将应用程序代码变量定义为可为空,但如果为空则将其设置为 0。如果将空值从数据库传递给您的应用程序变量,是否只是为了避免异常?如果您的应用程序并不绝对需要可空的十进制变量,只需在读取它时检查它是否为 DbNull:

decimal myAppVal = rdr["DbColumn"] == DBNull.Value 
   ? default(decimal) 
   : (decimal) rdr["DbColumn"];
Run Code Online (Sandbox Code Playgroud)

或明确设置 0.0M 而不是使用默认值(十进制)

在设计方面,如果您发现自己经常这样做,那么我建议创建一个通用扩展方法来从数据库中读取值。通过这种方式,您可以确保避免无效转换并处理异常,但更重要的是,如果出现空值,则返回默认值。;)

类似的东西(我只是在这里吐痰):

public static T CastFromDbTo<T>(object readerObject)
{
    T returnVal = default(T);
    if (readerObject is T)
    {
        var myValue = (T) readerObject;
        returnVal = readerObject != DbNull.Value && myValue != null
                ? (T) readerObject 
                : default(T);
    }
    return returnVal;
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样获取你的价值:

var myAppValue = HelperClass.CastFromDbTo<decimal>(rdr["DbColumn"]);
Run Code Online (Sandbox Code Playgroud)

或实际进行扩展:

public static T CastFromDbTo<T>(this object readerObject)
{
    T returnVal = default(T);
    if (readerObject is T)
    {
        var myValue = (T) readerObject;
        returnVal = readerObject != DbNull.Value && myValue != null
                ? (T) readerObject 
                : default(T);
    }
    return returnVal;
}
Run Code Online (Sandbox Code Playgroud)

那么你可以这样做:

var myAppVal = rdr["DbColumn"].CastFromDbTo<decimal>();
Run Code Online (Sandbox Code Playgroud)