• C# in Depth-简单的数据类型


    C# 1中定义的产品类型

    以定义一个表示产品的类型作为开始,然后进行处理。

    其中Product 类型内部封装了几个属性。同时还要创建预定义产品的一个列表。

    //代码清单1-1
    public class Product
    {
        string name;
        public string Name { get { return name; } }
        decimal price;
        public decimal Price { get { return price; } }
        public Product(string name,decimal price)
        {
            this.name = name;
            this.price = price;
        }
        public static ArrayList GetSampleProducts()
        {
            ArrayList list = new ArrayList();
            list.Add(new Product("A", 1.99m));
            list.Add(new Product("B", 2.99m));
            list.Add(new Product("C", 3.99m));
            list.Add(new Product("D", 4.99m));
            return list;
        }
    }

    以上C# 1代码存在如下3个局限:

    ①ArrayList 没有提供与其内部内容有关的编译时信息。不慎在 GetSampleProducts 创建的列表中添加一个字符串是完全有可能的,而编译器对此没有任何反应。

    ②代码中为属性提供了公共的取值方法,这意味着如果添加对应的赋值方法,那么赋值方法也必须是公共的。

    ③用于创建属性和变量的代码很复杂——封装一个字符串和一个十进制数应该是一个十分简单的任务,不该这么复杂。

    来看看C# 2作了哪些改进。


    C# 2中的强类型集合

    我们所做的第一组改动,针对上面列出的前两项,包含C# 2中最重要的改变:泛型。

    //代码清单1-2
    public class Product
    {
        string name;
        public string Name
        {
            get { return name; }
            private set { name = value; }
        }
        decimal price;
        public decimal Price
        {
            get { return price; }
            private set { price = value; }
        }
        public Product(string name,decimal price)
        {
            Name = name;
            Price = price;
        }
        public static List<Product> GetSampleProducts()
        {
            List<Product> list = new List<Product>();
            list.Add(new Product("A", 1.99m));
            list.Add(new Product("B", 2.99m));
            list.Add(new Product("C", 3.99m));
            list.Add(new Product("D", 4.99m));
            return list;
        }
        public override string ToString()
        {
            return string.Format("{0}:{1}", name, price);
        }
    }

    现在属性拥有了私有的赋值方法(我们在构造函数中使用了这两个赋值方法)。

    并且它能非常“聪明”地猜出 List<Product> 是告知编译器列表中只能包含 Product 。

    试图将一个不同的类型添加到列表中,会造成编译时错误,并且当你从列表中获取结果时,也并不需要转换结果的类型。

    C# 2解决了原先的3个问题中的2个。下面展示了展示了C# 3如何解决剩下的那个问题。


    C# 3中自动实现的属性

    自动实现的属性和简化的初始化,相比Lambda表达式等特性来说,有点微不足道,不过它们可以大大地简化代码。

    //代码清单1-3
    public class Product
    {
        public string Name { get; private set; }
        public decimal Price { get; private set; }
        Product() { }
        public static List<Product> GetSampleProducts()
        {
            return new List<Product>()
            {
                new Product{Name="A", Price=1.99m},
                new Product{Name="B", Price=2.99m},
                new Product{Name="C", Price=3.99m},
                new Product{Name="D", Price=4.99m}
            };
        }
        public override string ToString()
        {
            return string.Format("{0}:{1}", Name, Price);
        }
    }

    不再有任何代码、可见的变量与属性关联,而且硬编码的列表是以一种全然不同的方式构建的。

    由于没有 name 和 price 变量可供访问,我们必须在类中处处使用属性,这增强了一致性。

    现在有一个私有的无参构造函数,用于新的基于属性的初始化。(设置这些属性之前,会对每一项调用这个构造函数。)

    在本例中,实际上可以完全删除旧的公共构造函数。但这样一来,外部代码就不能再创建其他的产品实例了。


    C# 4中的命名实参

    对于C# 4,涉及属性和构造函数时,我们需要回到原始代码。

    其中有一个原因是为了让它不易变:尽管拥有私有赋值方法的类型不能被公共地改变,但如果它也不能被私有地改变,将会显得更加清晰。

    不幸的是,对于只读属性,没有快捷方式,但C# 4允许我们在调用构造函数时指定实参的名称,

    如下所示,它为我们提供了和C# 3的初始化程序一样的清晰度,而且还移除了易变性(mutability)。

    //代码清单1-4
    public class Product
        {
            readonly string name;
            public string Name { get { return name; } }
            readonly decimal price;
            public decimal Price { get { return price; } }
            public Product(string name,decimal price)
            {
                this.name = name;
                this.price = price;
            }
            public static List<Product> GetSampleProducts()
            {
                return new List<Product>()
                {
                    new Product(name:"A", price:1.99m),
                    new Product(name:"B", price:2.99m),
                    new Product(name:"C", price:3.99m),
                    new Product(name:"D", price:4.99m)
                };
            }
            public override string ToString()
            {
                return string.Format("{0}:{1}", Name, Price);
            }
        }

    在这个特定的示例中,该特性的好处不是很明显,但当方法或构造函数包含多个参数时,它可以使代码的含义更加清楚——特别是当参数类型相同,或某个参数为 null 时。

    当然,你可以选择什么时候使用该特性,只在使代码更好理解时才指定参数的名称。

    图1-1总结了 Product 类型的演变历程。注意,图中没有涉及C# 5。这是因为C# 5主要特性(异步函数)面向的领域还没有太多的语言支持。稍后,我们将简单看一下。

    到目前为止,变化幅度都不大。事实上,泛型的加入( List<Product> 语法)或许是C# 2最重要的一个部分。

    我们现在只看到了它的部分用处,不过这只是刚刚开始。下一个任务是以字母顺序打印产品列表。

  • 相关阅读:
    IntelliJ Idea和IntelliJ webstrm 常用快捷键
    mybatis基础学习2---(resultType和resultMap的用法和区别)和setting的用法
    使用观察者模式观察线程的生命周期
    观察者设计模式介绍
    java的内存模型及缓存问题
    一个解释volatile关键字作用的最好的例子
    多线程的waitset详细介绍
    浅谈单例模式
    SimpleThreadPool给线程池增加自动扩充线程数量,以及闲时自动回收的功能
    SimpleThreadPool给线程池增加拒绝策略和停止方法
  • 原文地址:https://www.cnblogs.com/errornull/p/10014941.html
Copyright © 2020-2023  润新知