C# programming guide

  • Programming concepts
    • Attributes
      • [Overview]
      • Creating Custom Attributes
        • 可以从System.Attribute直接或者间接派生出一个标类来创建新属性
          • 可以用System.AttributeUsage修饰属性,比如要运行设置多次同一属性的话,要把AllowMultiple设置为亍值。
        • 指定一个属性其实相当于是构造一个属性类,并设置其成员的值
      • Accessing Attributes by Using Reflection
        • GetCustomAttributes可以获取属性对象(导致动态创建属性对象)
          • 也可以用GetCustomAttributesData
      • How to create a C/C++ union by using attributes
        • 可以使用System.Runtime.InteropServices.StructLayout属性来控制内存布局
    • Reflection
      • 勘察可以发现装配件、模块以及类型相关的信息,可以用勘察来
        • 动态创建某类型的现例
        • 将类型绑定到已有现例
        • 从现例获取类型,并访问类型中指定的方法、域属、辖属
        • 访问代码中的属性
      • GetType可以用来获取类型
        • 例子:Type type = i.GetType();,示例输出System.Int32
      • 获取装配件信息
        • 例子:Assembly info = typeof(int).Assembly;
      • C#中的关键字protected和internal在IL中无意义,在勘察用编口中不做使用
        • IL中对应的术语叫做Family和Assembly
        • internal使用IsAssembly来对应
        • protected internal使用IsFamilyOrAssembly来对应
      • Reflection overview

        • 指到了其他地方的文档……

Language-Integrated Query (LINQ)

  • Overview
    • 对SQL、XML等数据源的查询一半有专门的语言或者方式,以字符串的形式体现在编程语言中,然后在程序语言运行时才解析执行。这带来的问题是,错误无法在程序语言编译时就发现,影响使用体验。
    • LINQ在程序语言层面提供了一系列技术,让查询可以通过程序语言的结构来构建,可以增加编译时的检查。
    • LINQ技术包含但不限于
    • 开发者最经常处理的时LINQ表达式,由声明性的措辞写就。可以对数据源进行一系列操作。
    • IEnumerable合集例子:
      // Specify the data source.
      int[] scores = { 97, 92, 81, 60 };
      
      // Define the query expression.
      IEnumerable<int> scoreQuery =
      		from score in scores
      		where score > 80
      		select score;
      
    • 查询表达式概览
      • 单个查询表达式可以针对多个数据源
      • 查询表达式会检查类型
      • 查询表达式在使用时方执行
      • 编译时,根据C#规范,查询表达式被转化为Standard Query Operator方法调用
        • 也就是说,能用查询表达式,可以被方法调用完全表达,反之则不然
      • 查询表达式可以编译为表达式树体,或者递执体
        • IEnumerable<T>查询被编译成递执体
        • IQueryable<T> 查询则被编译查表达式树体
  • Getting Started with LINQ in C#
    • Introduction to LINQ Queries (C#)

      • Three Parts of a Query Operation
      • 所有的LINQ查询操作都分为三个不同的动作:
        • 获取数据源
        • 创建查询
        • 执行查询
      • The Data Source
        • LINQ需要LINQ provider的支持。
      • The Query
        • 查询表达式初始化一个查询变量。
      • Query Execution
        • Deferred Execution
          • 默认是延迟执行的。
          • 查询变量自身不持有查询结果,因此可以执行多次。
        • Forcing Immediate Execution
          • 查询中的聚合函数,比如Counter、Max、Average、First等,需要即时执行。
          • 可调用ToList或者ToArray方法来即时执行查询。
    • LINQ and Generic Types (C#)

    • Basic LINQ Query Operations (C#)

      • 列举了集中LINQ常见操作。
    • Data Transformations with LINQ (C#)

      • LINQ不仅可以获取数据,还可以对数据进行变换。
      • LINQ可以通过select句段创建新的类型:
        • 合并多个输入序列,到一个新类型的输出序列
        • 创建一个输出序列,其元素只包含原始序列中元素的个别辖属
        • 创建一个输出序列,其元素是经过处理的原始序列元素
        • 以不同的格式创建输出序列
      • Joining Multiple Inputs into One Output Sequence
        • 一个例子。
      • Selecting a Subset of each Source Element
      • Transforming in-Memory Objects into XML
        • 可以直接从select创建对象,比如:
          				var studentsToXML = new XElement("Root",
          						from student in students
          						let scores = string.Join(",", student.Scores)
          						select new XElement("student",
          											 new XElement("First", student.First),
          											 new XElement("Last", student.Last),
          											 new XElement("Scores", scores)
          										) // end "student"
          								); // end "Root"
          
      • Performing Operations on Source Elements
        • 可以直接在查询结果上执行运算,比如下面的:
                  IEnumerable<string> output = 
                      radii.Select(r => $"Area for a circle with a radius of '{r}' = {r * r * Math.PI:F2}");
          
          �考<https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated>
          
          
    • Type Relationships in LINQ Query Operations (C#)

      • Queries that do not Transform the Source Data 过。
      • Queries that Transform the Source Data 过。
      • Letting the compiler infer type information 过。
    • Query Syntax and Method Syntax in LINQ (C#)

      • 标准的Linq查询操作在System.Linq命名空间下。

      • Standard Query Operator Extension Methods

        • 采用方法措辞:
          IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0).OrderBy(n => n);
          
          �要注意的是,这些保准查询操作时采用extension methods的方式实现的,参考<https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods>。
          
          
      • Lambda Expressions 过。

      • Composability of Queries 略。

    • C# Features That Support LINQ

    • Walkthrough: Writing Queries in C# (LINQ)

      • 给了一个例子,但是数据源只是驻内存的目件合集。
  • Standard Query Operators Overview (C#)
    • Overview
      • 文首
        • 标准查询操作是形成LINQ模式的方法。此类方法大豆操作于序列,要么是IEnumerable<T>,要么是IQueryable<T>。 - 是Enumerable和Queryable标类的静态方法,定义为扩展方法。
        • 标准查询操作包括过滤、投射、聚合、排序等等
        • 标准查询操作的执行时机也不相同 - 返回单例现的立马执行 - 返回序列的延迟执行
        • 对于查询方法的呼召可以链接成一个查询
        • 文中给了一个例子
      • Query Expression Syntax
        • 常用的标准查询方法,会以C#或者VB语言关键字的形式出现在qeury expression中
      • Extending the Standard Query Operators
      • Related Sections(略)
      • Query Expression Syntax for Standard Query Operators
      • query expression在编译时转化为方法调用
      • Query Expression Syntax Table
        • Cast, from int i in numers
        • GroupBy, group...by
        • GroupJoin, join...in...on...equals...into...
        • Join, join...in...on...equals...
        • OrderBy, orderby
        • OrderByDesending, orderby ... descending
        • Select, select
        • SelectMany, 多个from句段
        • ThenBy, orderby ..., ...
        • ThenByDescending, orderby ..., ... descending
        • Where, where
      • Classification of Standard Query Operators by Manner of Execution
        • 文首 - 执行分类:立即或延迟 - 延迟分类:流式和非流式
        • Manners of Execution - Immediate
          • 返回标量结果的查询
          • 使用 Enumerable.ToList 或 Enumerable.ToArray可以强制立即执行 - Deferred
          • 通常返回的是IEnumerable<T>IOrderedEnumerable<TElement> - Streaming - Non-Streaming
        • Classification Table
          • 给出了一张表,说明每个操作的返回类型,以及相关特性
      • Sorting Data
        • 可以分两步排序
        • Methods
          • OrderBy,按照升序排列,对应orderby关键子
          • OrderByDescending
          • ThenBy,二次排序
          • ThenByDescending
          • Reverse,没有对应的C#关键字
        • Query Expression Syntax Examples
      • Join Operations
        • 有Join以及GroupJoin两个方法,按照键项来匹配两数据源,叫做equijoins
          • 关系型数据库中,Join对应内连结,GroupJoin没有对应
        • Methods(过)

        • Query expression syntax examples(略)

  • LINQ to Objects (C#)
    • 可以要单独列一篇记录。
  • LINQ to ADO.NET (Portal Page)
  • Enabling a Data Source for LINQ Querying
    • 要让数据源支持LINQ,有以下条件:
      • 实现IEnumerable<T> 接口,以支持查询
      • 创建标准查询操作对应的方法,例如Where,Select等
      • 实现IQueryable<T> 接口,以接收表达式树体形式的LINQ查询,来让LINQ可以以自定义的方式执行,比如在远程执行
      • 让数据源适配已有的LINQ技术,这样不仅可以查询,还可以支持插入、更新以及删除操作
    • How to Enable LINQ Querying of Your Data Source
      • 对于驻内存的数据,如果实现了IEnumerable<T>,就可以用LINQ to Objects查询。 或者实现LINQ标准查询操作方法,但注意要延迟执行。
      • 对于远端的数据,实现IQueryable<T>比较好。
    • IQueryable LINQ Providers
      • LINQ提供方对IQueryable<T>的实现可能有不同的复杂度。
      • 高复杂度的比如LINQ to SQL,需要在LINQ和SQL之间对应。
      • 中复杂度的LINQ提供方需要做两两的类型映射。
      • 低复杂度的LINQ往往对应于某些特定的查询。
  • Visual Studio IDE and Tools Support for LINQ (C#)

Classes, Structs, and Records

  • Properties
    • Properties overview
      • 提供一种灵活的机制,用以读写以及计算私有域属的量值
      • 辖属看似域属,但实际上是特殊的方法,叫做accessors
      • Properties overview

        • 可以这么安排,域属是公开的,对应的实现是私有的
        • 支持get、set方法,C# 9以后支持init;这些方法可以有不同的访问级别
        • set、init中可以使用value关键字
        • 可以是读写的、只读的、只写的(少见)
      • Properties with backing fields

        • 可以用一个域属做背后支撑
      • Expression body definitions

        • 支持下面的形式
          • public string Name => $"{_firstName} {_lastName}";
          •   public decimal Price
              {
              	get => _cost;
              	set => _cost = value;
              }
            
      • Auto-implemented properties

        • 自动生成实现,形如public decimal Price { get; set; }
        • 也支持get和init
        • 可以有不同的访问等级
      • Required properties

        • C# 11,可以使用required来强制要求客户端来初始化
        • 例如
          • public required string Name { get; set; }
          • 客户端代码var item = new SaleItem { Name = "Shoes"};
      • C# Language Specification

  • Methods
    • Extension Methods
      • 文首
        • 可以往既有类型添加方法,无须创建新派生类型,或重新编译等。
        • 调用扩展方法和调用自身方法无明显区别
        • 最常见的扩展方法是往System.Collections.IEnumerable和System.Collections.Generic.IEnumerable<T>上添加的LINQ查询操作符
      • OrderBy Example
        • 扩展方法必须是静态的,其所属的标类也必须是静态的
        • 扩展方法无法访问私有成员
        • 使用扩展方法,只需打开其标类所在的命名空间(或许还要引用到其装配件)
        • 一个string扩展方法的例子public static int WordCount(this string str),注意到this的使用
      • Binding Extension Methods at Compile Time
        • 扩展方法无法覆盖标类的既有方法
      • Example
        • 此实例中,静态标类Extensions含有为接口IMyInterface实现的扩展方法
      • Common Usage Patterns
        • Collection Functionality
        • Layer-Specific Functionality
        • Extending Predefined Types
      • General Guidelines
        • 总之,一些注意事项
          • 如果目的标类有同名方法,那么扩展方法不会被调用
          • 扩展方法通过命名空间导入
        • 扩展方法最好不要用于控制Assembly Versioning
    • How to implement and call a custom extension method
      • To define and call the extension method
      • Example(略)
      • .NET Security(无碍)
    • How to create a new method for an enumeration
      • Example

(本篇完)