在现有对象中实现Nullable类型

时间:2010-01-07 05:23:23

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

我正在升级已在其业务和数据层对象中实现了Home-brew Constants类的现有应用程序。

我想用Nullable类型替换它,并使用常量类替换它,看起来像这样,但是所有非可空数据类型都是:

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

这会导致将对象属性保存到Db时出现一些混淆,因为必须检查所有小数和整数的psudo 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的空检查将是多余的。我仍然想知道实现此对象的代码是否可以从类型更改到十进制? 十进制

的任何问题

2 个答案:

答案 0 :(得分:5)

public decimal? UnitPrice { get; set; }

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

我觉得这绝对没问题。这就是它的工作方式。

答案 1 :(得分:0)

我对上面的属性集方法的实现有点不清楚,因为小数永远不能为null,所以我认为这个测试是多余的。我将包含一些示例代码,这些代码可以放入一个应该为您清理的控制台应用程序中。

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

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

实施例

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  

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

如果有更多具体的实施细节与您进行转换,请与我们联系。