深入理解C#(第3版)-- 第1章 C#开发的进化史(学习笔记)

1.1.1 C#1中定义的产品类型

代码清单1-1 Product类型(C#1)

using System.Collections;

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 Arraytist GetSampleProducts()
    {
        ArrayList list = new ArrayList();
        list.Add(new product("West Side Story", 9.99m));
        list.Add(new Product("Assassins", 14.99m));
        list.Add(new Product("Froge", 13.99m));
        list.Add(new Product("Sweeney Todd", 10.99m));
        return list;
    }
    
    public override string Tostring()
    {
        return string.Format("{o}:{1}", name, price);
    }
}

代码存在如下3个局限:

  • ArrayList没有提供与其内部内容有关的编译时信息。不慎在GetSampleProducts创建的列表中添加一个字符串是完全有可能的,而编译器对此没有任何反应。
  • 代码中为属性提供了公共的取值方法,这意味着如果添加对应的赋值方法,那么赋值方法也必须是公共的。
  • 用于创建属性和变量的代码很复杂。

1.1.2 C#2中的强类型集合

针对上面列出的前两项,包含C#2中最重要的改变:泛型。新的内容用粗体列出。

代码清单1-2 强类型集合和私有的赋值方法(C#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 = now List<Product>();
        list.Add(new Product("West Side Story", 9.99m));
        list.Add(new Product("A8sagsing", 14.99m));
        list.Add(new Product("Frogen", 13.99m));
        list.Add(new Product("Sweeney Todd", 10.99m));
        return list;
    }
    public override string ToString()
    {
        return string.Format("{o}:{1}", name, price);
    }
}

现在,属性拥有了私有的赋值方法(我们在构造函数中使用了这两个赋值方法)。并且它能非常“聪明”地猜出ist<Product>是告知编译器列表中只能包含Product。

1.1.3 C#3中目动实现的属性

代码清单1-3 自动实现的属性和更简单的初始化(C#3)

using System. Collections. Generic;

class Product
{
    public string Name
    {
        get;
        private set;
    }
    public decimal Price
    {
        get;
        private set;
    }

    public Product(string name, decimal price)
    {
        Name = name;
        Price = price;
    }

    Product() {}

    public static List<Product> GetSampleProducts()
    {
        return new List<Product>
        {
            new Product { Name = "West side story", Price = 9.99m},
            new Product { Name = "A#8assins", Price = 14.99m},
            new Product { Name = "Frog8", Price = 13.99m},
            new Product { Name = "gweeney Todd", Price = 10.99m}
        };
    }

    public override string Tostring()
    {
        return string. Format("{0}:{1)", Name, Price);
    }
}

1.1.4 C#4中的命名实参

C#4允许我们在调用构造函数时指定实参的名称

代码清单1-4 命名实参带来了清晰的初始化代码(C#4)

using System.Collections.Generic;

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: "West 8ide 8tory", price: 9.99m),
            new Product(name: "A8sassing", price: 14.99m),
            new Product(name: "Frogs", price: 13.99m),
            new Product(name: "Sweeney Todd", price: 10.99m)
        };
    }
    public override string Tostring()
    {
        return string.Format("{0}:{1}", name, price);
    }
}

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

1.2排序和过滤

1.2.1按名称对产品进行排序

实现了IComparer

代码清单1-5 使用IComparer对ArrayList进行排序(C#1)

class ProductNameComparer: IComparer
{
    public int Compare(object x, object y)
    {
        Product first = (Product)x;
        Product second = (Product)y;
        return first.Name.CompareTo(second.Name);
    }
}

...
ArrayList products = Product.GetSampleProducts();
products.Sort(new ProductNameComparer());

“泛型”

代码清单1-6 使用IComparer<Product>对List<Product>进行排序(C#2)

class ProductNameComparex: IComparer<Product>
{
    public int Compare(Product x, Product y)
    {
        return x.Name.CompareTo(y.Name);
    }
}

代码清单1-7 使用Comparison<Product>对List<Product>进行排序(C#2)

producta.Sort(
    delegate(Product x, Product y)
    {
        return x.Mame.Comparero(y.Mame);
    }
);

能直接指定要进行的比较,就能开始对产品进行排序,而不需要实现一个接口来做这件事。

代码清单1-8 在使用Lambda表达式中使用Comparison<Product>进行排序(C#3)

product.Sort((x, y) => x.Name.Comparero(y.Name));

将匿名方法替换成一种更简洁的创建委托实例的方式

代码清单1-9 在使用一个扩展方法List<Product>进行排序(C#3)

products.OrderBy(p =>p.Name);

 1.2.2查询集合

 代码清单1-10   循环、测试和打印(C# 1 )

ArrayList products = Product.GetSampleProducts();
foreach (Product product in products)
{
    if (product.Price > 10m)
    {
        Console.WriteLine(product);
    }
}

代码清单1-11   测试和打印分开进行(C# 2 )

List<Product>products = Product.GetSampleProducts();

Predicate<Product> test = delegate(Product p)
{
    return p.Price > 10m;
};

List<product>matches = products.FindAll(test);

Action<product> print = Console.WriteLine;
matches.ForEach(print);

print 变量的初始化使用了C# 2 的另一个特性——方法组转换,它简化了从现有方法创建委托的过程。

代码清单1-13   用Lambda表达式来测试(C# 3 )

products.Where(p =>p.Price >10)

1.3  处理未知数据

假定产品列表不仅包含现售的产品,还包括尚未面市的产品。某些情况下,我们可能不知道价格。
如果decimal是引用类型,那么只需使用null来表示未知的价格。

1.3.1  表示未知的价格

在C# 1 中如何表示?有3种常见的解决方案: 
 围绕decimal创建一个引用类型包装器; 
 维护一个单独的Boolean标志,它表示价格是否已知; 
 使用一个“魔数”(magic value )(比如 decimal.MinValue )来表示未知价格。

.NET 2.0 通过引入Nullable<T> 结构

在C# 3 中为了检查一个价格是否已知,可以把它同null比较,或者使用HasValue 属性。

1.3.2  可选参数和默认值

有时你并不想给出方法所需的所有东西,比如对于某个特定参数,你可能总是会使用同样的值。传统的解决方案是对该方法进行重载,现在C# 4引入的可选参数(optional parameter )可以简化这一操作。

public Product(string name, decimal? price = nul1)
{
    ...
}

 1.4  LINQ简介

LINQ(Language Integrated Query,语言集成查询),是 C# 3的核心。顾名思义,LINQ是关于查询的,其目的是使用一致的语法和特性,以一种易阅读、可组合的方式,使对多数据源的查询变得简单。

1.4.1  查询表达式和进程内查询

查询表达式

隐式类型局部变量(implicitly typed local variable),它使用var 上下文关键字声明。

代码清单1-16   连接(joining )、过滤(filtering)、排序(ordering)和投影(projecting )(C# 3 )

List<Product> products = Product.GetSampleProducts();
List<Supplier> suppliers = Supplier.GetSampleSuppliers();
var filtered = from p in products
               join s in suppliers
                  on p.SupplierID equals s.SupplierID
               where p.Price > 10
               orderby s.Name, p.Name
               select new { SupplierName = s.Name, ProductName = p.Name };
foreach (var v in filtered)
{
   Console.WriteLine("Supplier={0}; Product={1}",
                     v.SupplierName, v.ProductName);
}

1.4.2 查询XML

代码清单1-17   用LINQ to XML 对XML文件进行“复杂”的处理(C# 3 ) 

XDocument doc = XDocument.Load("data.xml");
var filtered = from p in doc.Descendants("Product")
               join s in doc.Descendants("Supplier")
                  on (int)p.Attribute("SupplierID")
                  equals (int)s.Attribute("SupplierID")
               where (decimal)p.Attribute("Price") > 10
               orderby (string)s.Attribute("Name"),
                       (string)p.Attribute("Name")
               select new
              {
                   SupplierName = (string)s.Attribute("Name"),
                   ProductName = (string)p.Attribute("Name")
              };
foreach (var v in filtered)
{
    Console.WriteLine("Supplier={0}; Product={1}",
                      v.SupplierName, v.ProductName);
}

1.4.3  LINQ to SQL

为什么要将所有数据都从数据库里“拽”回来,再应用这些.NET查询和排序呢?为什么不直接让数据库来做这些事情呢?那不正是它擅长的事情吗?事实上,这正是LINQ to SQL所做的事情。发出了一个数据库请求,它基本上被转换为SQL 查询。虽然查询是用C#代码来表示的,但却是作为SQL 来执行的。

1.5  COM(Component Object Model)和动态类型

LINQ是C# 3 的主要内容,而互操作性是C# 4 最重要的主题。

1.5.1 简化COM互操作

使用命名实参

C# 4还支持命名索引器

1.5.2  与动态语言互操作

dynamic

1.6  轻松编写异步代码

C# 5 的超级特性:异步函数。

Windows Forms中的线程有两条金科玉律:不能阻塞UI线程,并且不能在任何其他线程中访问UI元素(除非使用一些明确指定的方法)。

1.7 剖析.NET 平台

C#语言本身的特性、运行时的特性(可以认为运行时提供了程序运行的一个“引擎”)以及.NET框架库的特性。

1.7.1  C#语言

C#语言是由它的规范定义的。C#规范描述了C#源代码的格式,其中包括语法和行为。

C#编译器除了可以以IL (Intermediate Language ,中间语言)形式输出外,还可以以其他合法形式输出。

1.7.2  运行时

(Common Language Infrastructure ,公共语言基础设施)

CLI的运行时部分称为CLR (公共语言运行时)

1.7.3  框架库

.NET 中的框架库主要是以IL 的形式构建的,只有在必要时才使用本地代码。

.NET一词是指微软公司提供的运行时和库的组合,其中也包含C#和VB.NET编译器。

 

 

 

c-sharp-in-depth-third-edition

posted @ 2019-09-29 18:44  FH1004322  阅读(278)  评论(0)    收藏  举报