【问题标题】:How can I replace an empty or null val with a default "base" value?如何用默认的“base”值替换空或 null val?
【发布时间】:2013-11-25 19:24:25
【问题描述】:

使用以下代码:

foreach (JObject obj in arr)
{
    id = (string)obj["Id"];
    packSize = (Int16)obj["PackSize"];
    var description = (string)obj["Description"];
    var deptSubdept = (Double)obj["DeptDotSubdept"];
    var unitCost = (Double)obj["Unit_Cost"];
    var unitList = (Double)obj["Unit_List"];
    var UPC_Code = (string)obj["UPC_code"];
    var UPC_packSize = (Int16)obj["UPC_pack_size"];
    var CRVId = (Int32)obj["CRV_Id"];

inventoryItems.Add(new WebAPIClientUtils.InventoryItem
{
    Id = id,
    PackSize = packSize,
    Description = description,
    DeptDotSubdept = deptSubdept,
    Unit_Cost = unitCost,
    Unit_List = unitList,
    UPC_code = UPC_Code,
    UPC_pack_size = UPC_packSize,
    CRV_Id = CRVId
});

...我得到,“System.ArgumentException:输入字符串的格式不正确。无法将 存储在成本列中。预期类型为 Double。---> System.FormatException ..."

注意:“成本”是本地表中以这种方式定义的列的名称:

// Create temp table that mirrors InventoryItems as a staging area for the data to be bulk copied
var dt = new DataTable();
dt.Columns.Add(new DataColumn("Id", typeof(string)));
. . .
dt.Columns.Add(new DataColumn("Cost", typeof(double)));
. . .

因此,当检索到的数据具有这些虚假/空值时,我如何检查并使用诸如 0.00 表示双精度值、0 表示 int、string.empty 表示 String 等值?

为了查看何时发生这种情况,我在这一行放置了一个条件断点:

var unitCost = (Double)obj["Unit_Cost"];

...通过在断点条件对话框中输入以下内容:

unitCost.ToString() == ""

...但它永远无法到达。我还尝试将“unitCost == null”设置为条件断点,结果相同。

更新

有了这个:

id = (string)obj["Id"] ?? string.Empty;
packSize = (Int16)obj["PackSize"] ?? 0;
var description = (string)obj["Description"] ?? string.Empty;
var deptSubdept = (Double)obj["DeptDotSubdept"] ?? 0.0;
var unitCost = (Double)obj["Unit_Cost"] ?? 0.0;
var unitList = (Double)obj["Unit_List"] ?? 0.0;
var UPC_Code = (string)obj["UPC_code"] ?? string.Empty;
var UPC_packSize = (Int16)obj["UPC_pack_size"] ?? 0;
var CRVId = (Int32)obj["CRV_Id"] ?? 0;

...我明白了:

操作员 '??'不能应用于“short”和“int”类型的操作数 操作员 '??'不能应用于“double”和“double”类型的操作数 操作员 '??'不能应用于“int”和“int”类型的操作数

更新 2

我试过了:

double unitCost;
if (obj["Unit_Cost"] != DBNull.Value)
{
    unitCost = (Double) obj["Unit_Cost"];
}
else
{
    unitCost = 0.0;
}

...并得到,“运算符 '!=' 不能应用于类型为 'Newtonsoft.Json.Linq.JToken' 和 'System.DBNull' 的操作数

更新 3

将条件赋值的初始部分包含在括号中,如下所示:

var UPC_Code = ((string)obj["UPC_code"]) ?? string.Empty;

...仅适用于字符串;对于其他数据类型(int 和 double),我仍然会收到错误消息。

更新 4

这段代码发生了运行时异常:

dt.Rows.Add(invItem.Id, invItem.PackSize, invItem.Description, invItem.DeptDotSubdept,  
    invItem.Unit_Cost, invItem.Unit_List, invItem.UPC_code, invItem.UPC_pack_size, 
    invItem.CRV_Id);

...所以我尝试了这个:

int packSize = 1;
double unitCost = 0.0;
double unitList = 0.0;

if (invItem.PackSize != null)
{
    packSize = invItem.PackSize;
}
if (invItem.Unit_Cost != null)
{
    unitCost = invItem.Unit_Cost;
}
if (invItem.Unit_List != null)
{
    unitList = invItem.Unit_List;
}

dt.Rows.Add(invItem.Id, packSize, invItem.Description, 
    invItem.DeptDotSubdept, unitCost, unitList, invItem.UPC_code, 
    invItem.UPC_pack_size, invItem.CRV_Id);

...但它仍然失败,并且“!= null”行在编辑器中有蓝色波浪线的情况。

更新 5

关于 SLaks 的建议,我试过了:

if (obj["Unit_Cost"] == DBNull.Value)
{
    unitCost = 0.0;
}
else
{
    unitCost = (Double)obj["Unit_Cost"];
}

...但是得到,“运算符 '==' 不能应用于 'Newtonsoft.Json.Linq.JToken' 和 'System.DBNull' 类型的操作数

我对此也有同样的看法:

if ((Double)obj["Unit_Cost"] == DBNull.Value)

....还有这个:

if (((Double)obj["Unit_Cost"]) == DBNull.Value)

更新 6

我看到当这失败时,unitCost 的值不是 null,而是 0。所以,我在分配该值的位置设置了一个断点:

unitCost == 0

...但是断点被命中,即使该值为 0.0(这很好)。我认为即使是 0 也可以,但是......它失败了,所以这个值显然有问题。

【问题讨论】:

  • 你的断点不起作用,因为你没有设置unitCost
  • 你怎么看?断点在这一行: var unitCost = (Double)obj["Unit_Cost"];
  • 要更新:您需要括号,否则演员表(拆箱)在 空合并之前。
  • @JeppeStigNielsen:你的意思是把所有东西都封装到合并操作符上吗?
  • @ClayShannon:没错。直到之后该行运行,unitCost 尚未设置。而且您将无法将nullDBNull.Value"" 转换为双精度。

标签: c# null double default-value argumentexception


【解决方案1】:

根据this answer和你最近有什么类型的信息,尝试做:

id = obj.Value<string>("Id") ?? "";
packSize = obj.Value<short?>("PackSize") ?? (short)0;
var description = obj.Value<string>("Description") ?? "";
var deptSubdept = obj.Value<double?>("DeptDotSubdept") ?? 0.0;
var unitCost = obj.Value<double?>("Unit_Cost") ?? 0.0;
...
var crvId = obj.Value<int>("CRV_Id") ?? 0;

【讨论】:

    【解决方案2】:

    您看到的是DBNull.Value,它会覆盖ToString() 以返回""

    检查

    if (obj["Unit_Cost"] == DBNull.Value)
    

    如果objDataRow,你也可以调用obj.IsNull("Unit_Cost")

    【讨论】:

      【解决方案3】:

      对于默认值,您可以使用 var def = (Double)(obj["Unit_Cost"] ?? default(Double));

      【讨论】:

        【解决方案4】:

        如果您使用DeserializeObject 而不是JObject,您可以使用DefaultValueAttributeDefaultValueHandling 轻松做到这一点:

        void Main()
        {
            var item = JsonConvert.DeserializeObject<InventoryItem>(@"{""Id"": 1}",
                 new JsonSerializerSettings {
                        DefaultValueHandling = DefaultValueHandling.Populate });
            // item.PackSize == 1
        }
        public class InventoryItem
        {
            public string Id { get; set; }
            [DefaultValue(1)]
            public Int16 PackSize { get; set; }
            [DefaultValue("")]
            public string Description { get; set; }
            public Double DeptDotSubdept { get; set; }
        }
        

        【讨论】:

          【解决方案5】:

          试试这个

          Double dbl;
          Int16 int16;
          Int32 int32;
          
              foreach (JObject obj in arr)
              {
                  id = (string)obj["Id"];
                  packSize = Int16.TryParse(obj["PackSize"].ToString(), out int16) ? (Int16)obj["PackSize"]:0;
                  var description = (string)obj["Description"];
                  var deptSubdept = Double.TryParse(obj["DeptDotSubdept"].ToString(), out dbl) ? (Double)obj["DeptDotSubdept"] : 0.00;
                  var unitCost = Double.TryParse(obj["Unit_Cost"].ToString, out dbl) ? (Double)obj["Unit_Cost"] : 0.00;
                  var unitList = Double.TryParse(obj["Unit_List"].ToString(), out dbl) ? (Double)obj["Unit_List"] : 0.00;
                  var UPC_Code = (string)obj["UPC_code"];
                  var UPC_packSize = Int16.TryParse(obj["UPC_pack_size"].ToString(), out int16) ? (Int16)obj["UPC_pack_size"] : 0;
                  var CRVId = Int32.TryParse(obj["CRV_Id"].ToString(), out int32) ? (Int32)obj["CRV_Id"] : 0;
          
              inventoryItems.Add(new WebAPIClientUtils.InventoryItem
              {
                  Id = id,
                  PackSize = packSize,
                  Description = description,
                  DeptDotSubdept = deptSubdept,
                  Unit_Cost = unitCost,
                  Unit_List = unitList,
                  UPC_code = UPC_Code,
                  UPC_pack_size = UPC_packSize,
                  CRV_Id = CRVId
              })
          

          【讨论】:

            【解决方案6】:

            尝试使用as 运算符转换为可为空的类型并使用Nullable(T).GetValueOrDefault

            foreach (JObject obj in arr)
            {
                var id = obj["Id"] as string;
                var packSize = obj["PackSize"] as short?;
                var description = obj["Description"] as string;
                var deptSubdept = obj["DeptDotSubdept"] as double?;
                var unitCost = obj["Unit_Cost"] as decimal?;
                var unitList = obj["Unit_List"] as decimal?;
                var UPC_Code = obj["UPC_code"] as string;
                var UPC_packSize = obj["UPC_pack_size"] as short?;
                var CRVId = obj["CRV_Id"] as int?;
            
                inventoryItems.Add(new WebAPIClientUtils.InventoryItem
                {
                    Id = id ?? string.Empty,
                    PackSize = packSize.GetValueOrDefault(),
                    Description = description ?? string.Empty,
                    DeptDotSubdept = deptSubdept.GetValueOrDefault(),
                    Unit_Cost = unitCost.GetValueOrDefault(),
                    Unit_List = unitList.GetValueOrDefault(),
                    UPC_code = UPC_Code ?? string.Empty,
                    UPC_pack_size = UPC_packSize.GetValueOrDefault(),
                    CRV_Id = CRVId.GetValueOrDefault()
                });
            }
            

            也可以使用decimal 表示货币。

            【讨论】:

              猜你喜欢
              • 2012-09-04
              • 2021-11-08
              • 2017-11-01
              • 1970-01-01
              • 2016-12-11
              • 2016-04-15
              • 2019-08-08
              • 2014-03-31
              • 2017-10-06
              相关资源
              最近更新 更多