简体   繁体   English

C#,Nullable十进制

[英]C#, Nullable decimal

In my database, v1 field is nullable field. 在我的数据库中,v1字段是可空字段。 but I define 0 (default) if the value is null. 但如果值为null,我定义0(默认值)。

public decimal? v1 {
  get {
    return this._v1; 
  }
  set {
    this._v1 = value ?? 0M;
  }
}

so now, the v1 is not nullable variable anymore. 所以现在,v1不再是可空变量了。

but I can not do this, 但我不能这样做,

decimal v2 = v1;

The error message say, Cannot implicitly convert type 'decimal?' 错误信息说,不能隐式转换类型'decimal?' to 'decimal'. 到'十进制'。

In this case, Do I have to convert to decimal, like this? 在这种情况下,我是否必须转换为十进制,像这样?

decimal v2 = Convert.ToDecimal(v1);

It very annoying job. 这是非常讨厌的工作。 and codes are look dirty too. 而且代码看起来也很脏。

Anyone know better solution? 谁知道更好的解决方案 please advice me. 请指教。

No you don't have to convert the decimal? 不,你不必转换decimal? , you have access to the underlying value from the Nullable type eg ,您可以访问Nullable类型的基础值,例如

decimal v2 = v1.Value;

Assigning a default value to a Nullable type does not make it non-nullable, it just means it has a value. Nullable类型分配默认值不会使其不可为空,它只是意味着它具有值。 Nullable types have a HasValue property which helps you determine this. Nullable类型具有HasValue属性,可帮助您确定此属性。

Just for the record, I wouldn't recommend defaulting the value to 0 it would probably make more sense letting it default to null considering it can indeed be null. 只是为了记录在案,我不会推荐值默认为0 ,它可能会更有意义让它默认为null考虑到它确实可以为null。 If you need to have a default value in your app you will probably want to use the GetValueOrDefault method eg 如果您需要在应用程序中使用默认值,则可能需要使用GetValueOrDefault方法,例如

decimal v2 = v1.GetValueOrDefault(0m);

The easiest way to convert a decimal? 转换decimal?的最简单方法是decimal? to decimal but have the value to be 0 when null , you can do: 对于decimal但是当null0时,您可以执行以下操作:

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

Read up on GetValueOrDefault 阅读GetValueOrDefault

You could also call GetValueOrDefault with no arguments, which will yield default(T) , which in the case of Decimal is 0, but I like to be explicit. 你也可以调用没有参数的GetValueOrDefault ,它将产生default(T) ,在Decimal的情况下是0,但我喜欢显式。

I'm curious why you would define your app code variable as nullable but then set it to 0 if it's null. 我很好奇为什么你要将你的应用程序代码变量定义为可空,但如果它为null则将其设置为0。 Is it just to avoid the exception if passing a null value from the database to your app variable? 如果将空值从数据库传递到app变量,是否只是为了避免异常? If your application doesn't absolutely need the nullable decimal variable, just check it for a DbNull as you're reading it out: 如果你的应用程序不是绝对需要可以为空的十进制变量,那么只要在你读出它时检查它是否为DbNull:

decimal myAppVal = rdr["DbColumn"] == DBNull.Value 
   ? default(decimal) 
   : (decimal) rdr["DbColumn"];

or explicitly set 0.0M instead of using default(decimal) 或明确设置0.0M而不是使用默认值(十进制)

Design-wise, if you're finding yourself doing this often, then i'd suggest creating a generic extension method to read values out of the database. 设计方面,如果您发现自己经常这样做,那么我建议创建一个通用的扩展方法来从数据库中读取值。 This way you can ensure that invalid casts are avoided and exceptions are handled, but more importantly that default values are returned in case of nulls. 这样,您可以确保避免无效的强制转换并处理异常,但更重要的是,如果为空,则返回默认值。 ;) ;)

Something like (and I'm just spitballing here): 有点像(我只是在这里吐痰):

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

Then you could grab your value like this: 然后你可以像这样抓住你的价值:

var myAppValue = HelperClass.CastFromDbTo<decimal>(rdr["DbColumn"]);

or actually make an extension: 或实际进行扩展:

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

then you could just do this: 然后你可以这样做:

var myAppVal = rdr["DbColumn"].CastFromDbTo<decimal>();

The Value you assigned to v1 is decimal , but the type is still decimal? 您为v1指定的值是decimal ,但类型仍为decimal? . That's why you can't assing it. 这就是你无法解决的原因。

Try 尝试

decimal v2 = v1.Value;

Nullable Types have the properties Value and HasValue . Nullable Types具有ValueHasValue属性。

HasValue - Gets a value indicating whether the current Nullable object has a value. HasValue - 获取一个值,该值指示当前Nullable对象是否具有值。

Value - If HasValue is true, this contains the value if not its null. - 如果HasValue为true,则包含值,如果不为null。

decimal v2;

if (v1.HasValue) // check for null
{
  v2 = v1.Value;
}

Check out MSDN - Nullable Types (C# Programming Guide) 查看MSDN - Nullable Types(C#编程指南)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM