【问题标题】:Implementing Nullable types in existing objects在现有对象中实现 Nullable 类型
【发布时间】:2010-01-07 05:23:22
【问题描述】:

我正在升级已在其业务和数据层对象中实现自制常量类的现有应用程序。

我想用 Nullable 类型替换它,并用常量类替换它,看起来像这样,但使用所有不可为 null 的数据类型:

class Constants
{
    public static int nullInt
    {
        get { return int.MinValue; }
    }
}

这些常量值被用作几乎所有对象属性的默认值,如下所示:

private decimal _unitPrice = Constants.nullInt;
public decimal UnitPrice
{
    get { return _unitPrice; }
    set { _unitPrice = (value == null) ? Constants.nullInt : value; }
}

这会导致在将对象属性保存到 Db 时出现一些混淆,因为必须检查所有小数和整数是否有伪 null 值,否则您会将 int.MinValue 之类的内容保存到 Db。

    private void Save()
    {
        //Datalayer calls and other props omitted
        SqlParameter sqlParm = new SqlParameter();
        sqlParm.Value = (this.UnitPrice == Constants.nullInt) ? DBNull.Value : (object)this.UnitPrice;

    }

好的,现在的问题.. 我想改变使用 Nullable 值类型的东西,如下面的示例所示,属性会从小数变为小数吗?影响实现这些对象的任何代码?

    public decimal? UnitPrice { get; set; }

    private void Save()
    {
        //Datalayer calls and other props omitted
        SqlParameter sqlParm = new SqlParameter();
        sqlParm.Value = this.UnitPrice ?? DBNull.Value;
    }

编辑:感谢您对我的重构的双重检查,是的,对原始代码中属性的 SET 的空检查将是多余的。我仍然想知道实现此对象的代码是否会出现从 decimal

类型更改为 decimal? 的任何问题

【问题讨论】:

    标签: c# .net .net-3.5 nullable


    【解决方案1】:
    public decimal? UnitPrice { get; set; }
    
    private void Save()
    {
        //Datalayer calls and other props omitted
        SqlParameter sqlParm = new SqlParameter();
        sqlParm.Value = this.UnitPrice ?? DBNull.Value;
    }
    

    我觉得这绝对没问题。它应该是这样工作的。

    【讨论】:

      【解决方案2】:

      我有点不清楚上述属性设置方法的实现,因为小数永远不能为空,所以我认为这个测试是多余的。我包含了一些示例代码,这些代码可以放入控制台应用程序中,应该为您解决问题。

      由于切换到可以为空的数据类型,您几乎不会对代码进行重构。这将是您清理代码和避免当前实现的潜在缺陷的一个很好的举措。

      如果不出意外,您将获得的性能提升可能会让您的努力值得。可以这么说,没有什么是完全即插即用的,但是如果您查看下面的代码,您会发现您提供的场景几乎没有影响。

      示例

      using System;
      using System.Data.SqlClient;
      
      namespace NullableTypes
      {
          class Program
          {
              static class Constants
              {
                  public static decimal NullDecimal
                  {
                      get { return decimal.MinValue; }
                  }
              }
      
              public class ProductTheOldWay
              {
                  public string Name { get; set; }
                  public decimal UnitPrice { get; set; }
      
                  public ProductTheOldWay()
                  {
                      Name = string.Empty;
                      UnitPrice = Constants.NullDecimal;
                  }
      
                  public override string ToString()
                  {
                      return "Product: " + Name + " Price: " + 
                             ((UnitPrice == Constants.NullDecimal) 
                               ? "Out of stock" 
                               : UnitPrice.ToString());
                  }
      
                  public void Save()
                  {
                      //Datalayer calls and other props omitted
                      var sqlParm = new SqlParameter
                      {
                          Value = (UnitPrice == Constants.NullDecimal) 
                                   ? DBNull.Value 
                                   : (object)UnitPrice
                      };
      
                      //save to the database...
                      Console.WriteLine("Value written to the database: " + sqlParm.Value);
                  }
              }
      
              public class ProductTheNewWay
              {
                  public string Name { get; set; }
                  public decimal? UnitPrice { get; set; }
      
                  public ProductTheNewWay()
                  {
                      Name = string.Empty;
                  }
      
                  public override string ToString()
                  {
                      return "Product: " + Name + " Price: " + 
                             ((UnitPrice.HasValue) 
                               ? UnitPrice.ToString() 
                               : "Out of stock");
                  }
      
                  public void Save()
                  {
                      //Datalayer calls and other props omitted
                      var sqlParm = new SqlParameter
                      {
                          Value = UnitPrice
                      };
      
                      //save to the database...
                      Console.WriteLine("Value written to the database: " + sqlParm.Value);
                  }
              }
      
              static void Main()
              {
                  var oldProduct1 = new ProductTheOldWay
                  {
                      Name = "Widget",
                      UnitPrice = 5.99M
                  };
      
                  var oldProduct2 = new ProductTheOldWay
                  {
                      Name = "Rare Widget",
                      UnitPrice = Constants.NullDecimal // out of stock
                  };
      
                  Console.WriteLine(oldProduct1);
                  Console.WriteLine(oldProduct2);
      
                  Console.WriteLine("Saving...");
                  oldProduct1.Save();
                  oldProduct2.Save();
      
                  Console.ReadLine();
      
                  var newProduct1 = new ProductTheNewWay
                  {
                      Name = "Widget",
                      UnitPrice = 5.99M
                  };
      
                  var newProduct2 = new ProductTheNewWay
                  {
                      Name = "Rare Widget"
                      /* UnitPrice = null by default */
                  };
      
                  Console.WriteLine(newProduct1);
                  Console.WriteLine(newProduct2);
      
                  Console.WriteLine("Saving...");
                  newProduct1.Save();
                  newProduct2.Save();
      
                  Console.ReadLine();
      
                  // as a further example of the new property usage..
      
                  if (newProduct1.UnitPrice > 5)
                      Console.WriteLine(newProduct1);
      
                  Console.WriteLine("Using nullable types is a great way to simplify code...");
      
                  Console.ReadLine();    
              }
          }
      }
      

      输出

      Product: Widget Price: 5.99  
      Product: Rare Widget Price: Out of stock  
      Saving...  
      Value written to the database: 5.99  
      Value written to the database:  
      
      Product: Widget Price: 5.99  
      Product: Rare Widget Price: Out of stock  
      Saving...  
      Value written to the database: 5.99  
      Value written to the database:  
      
      Product: Widget Price: 5.99  
      

      使用可为空的数据类型是简化代码的好方法...

      如果有更具体的实施细节与您进行切换有关,请告诉我。

      【讨论】:

      • 另一个好处是代码更清晰,更易读。除了性能和可靠性问题之外,我相信这也是您想要进行转换的部分原因。
      猜你喜欢
      • 2021-06-05
      • 2011-06-09
      • 1970-01-01
      • 1970-01-01
      • 2020-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-10
      相关资源
      最近更新 更多