代码之家  ›  专栏  ›  技术社区  ›  Tj Kellie

在现有对象中实现可为空的类型

  •  5
  • Tj Kellie  · 技术社区  · 15 年前

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

    我想用可以为空的类型替换它,并去掉constants类,它看起来像这样,但是使用所有不可以为空的数据类型:

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

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

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

    这会导致在将对象属性保存到数据库时出现一些混乱,因为必须检查所有十进制和整数的psudo空值,否则会将int.minvalue之类的内容保存到数据库。

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

    好吧,现在问题是……我想使用可以为空的值类型来改变周围的情况,如下面的示例中所示,属性是否会从十进制更改为十进制?影响实现这些对象的代码吗?

        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 回复  |  直到 9 年前
        1
  •  5
  •   this. __curious_geek    15 年前
    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
  •  0
  •   Marcus Mangelsdorf user1542042    9 年前

    我有点不清楚上面的属性集方法的实现,因为十进制永远不能为空,所以我认为这个测试是多余的。我包含了一些可以放到控制台应用程序中的示例代码,这些应用程序可以为您清除一些内容。

    由于切换到可以为空的数据类型,您将很少经历代码的重构。在清理代码和避免当前实现的潜在缺陷方面,这将是一个很好的举措。

    如果没有别的,你将得到的性能提升可能会使你的努力值得一段时间。可以说,没有什么是完全即插即用的,但是如果你看下面的代码,你会发现在你提供的场景中影响很小。

    例子

    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  
    

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

    如果有更具体的实现细节需要您进行转换,请告诉我。