图解C#教程 《Illustrated C# 7.0 The C# Language Presented Clearly,Concisely, and Visually Fifth Edition》
Identifiers—标识符,理解为"变量名","类名"等名字。由于名字必须独一无二,所以用identifiers
(身份identity)
规则:
首字母:字母和下划线和@-----yes
首字母:数字------------no
后续字母:字母和下划线—yes
后续字母:数字-yes,@--no
Identifiers are case-sensitive(区分大小写的). For instance, the variable names myVar and MyVar are different identifiers.
As an example, in the following code snippet(代码片段), the variable declarations are all valid and declare different
integer variables. But using such similar names will make coding more error-prone and debugging more
difficult. Those debugging your code at some later time will not be pleased.
// Valid syntactically, but very confusing!不推荐用相似的identifiers
int totalCycleCount;
int TotalCycleCount;
int TotalcycleCount;
语句:statement
A statement is a source code instruction describing a type or telling the program to perform an action.
区块:Blocks
{ }----这个就是区块
A block is a sequence of zero or more statements enclosed by a matching set of curly braces(curly 弯曲的括号); it acts as a single syntactic statement.
.
不用结束的分号。
Semicolon –分号
Substitution markers 替代标记
string interpolation 字符插值
a compile error but a runtime error (called an exception).
Compile error 编译错误
Runtime error 运行时错误 exception 异常
Comments: Annotating the Code
Comment 初次学英文的意思:评论=>注释
Annotating:annotate 注解,an- note-
Span multiple lines 跨行
A C# Program Is a Set of Type Declarations
C#程序是一组类型声明(一组: set)
A Type is a Template
类型是一个模板,是用来创建数据结构的模板,data structure。
那么问题来了,这一系列类型(或者模板),是不是可以推理出,写代码的时候,用模板(或者类型)产生数据,尽可能与代码隔离?
不知道这种思想符合不符合开发程序代码的逻辑(我自己瞎想了一下!)
实例化类型 Instantiating a Type
Instant 在第一次接触英文中的意思是:立即!"立即"一个类型?
Creating an actual object from the type's template is called instantiating the type.
从某个类型模板中,创建一个实际的对象,成为实例化这个类型。
类型:
简单类型 ,比如 int,short,long,储存一个数据
数组类型,array可以储存多个,相同类型的数据(叫做元素element)
自定义类型,(一般指的是类class:包含data和function(method方法))
实际上,函数在内存中也是数据(地址+本身的也是一种数据),所以这么理解就好理解了。
但是函数本身是搬运或者产生数据的动作,是动词。本质上也是一种类型。函数类型。只不过,函数里面又可以包含一定的简单类型
比如int,或数组类型array等
预定义类型:
Predefined Types
C#提供了16种预定义的类型:
用户自定义类型有6种:
类类型 class
数组类型 array
结构类型 struct
枚举类型 enum
委托类型 delegate
接口类型 interface
User-Defined Types
Besides the 16 predefined types provided by C#, you can also create your own user-defined types. There are
six kinds of types you can create.
• class types
• struct types
• array types
• enum types
• delegate types
• interface types
因为declare type 就是创建模板,这个模板需要自己制作(也就是声明),而预定义类型,其实内部已经声明好了模板,故直接实例化就行
比如 直接 int a 这个int 就是内部已经搞好了 ,并不是凭空产生的。这就是自定义类型和普通类型的差异。
Stack的特征
- 数据增加或者删除,只能在stack的顶部,这就是后进先出,先进后出的原因
- 放入数据,叫做入栈,push(压入)
- 删除一个数据,叫做出栈,pop(弹出),push压入和pop弹出 这两个英语单词都太形象了
Heap堆
Value Types and Reference Types
值类型和引用类型
The type of a data item defines how much memory is required to store it and the data members that
comprise it. The type also determines where an object is stored in memory—the stack or the heap.
Types are divided into two categories: value types and reference types. Objects of these types are stored differently in memory.
Type=>类型的含义,就是告诉编译器要分配多少内存。以及如何存储,到底是stack还是heap。这就是type的全部内涵。
Type 又分为value type 和 reference type
• Value types require only a single segment of memory, which stores the actual data.
Value types 仅仅一个是一个内存的单片段,储存了实际的数据
• Reference types require two segments of memory.
Reference types 要求两段内存 (two segments of memory)
– The first contains the actual data—and is always located in the heap.
- 包含实际数据,这个部分一直存在堆里
– The second is a reference that points to where the data is stored in the heap - 是引用(指向存在堆里的数据),放在stack栈里面。
声明类declare class
对比理解就是,由于类是要我们自己创建的,并不像int a ,int b之类的预定义类型
直接实例化就行。需要我们自己建立模板,术语就叫做declare,声明。先声明,再实例化。自定义的类型,必须要有这两步!
Class member
类成员
翻译成员,和member的含义,不是特别符合,个人感觉。
Member就是类的成分,构成
Class member 类的构件
Member由field 和 method组成
Field 区域,这里翻译成字段
Method 是方法。
两步合并一步:
Class的方法调用
直接像vba这样调用是不行的。因为C#所有操作必须在类中进行。
这里我自己有一点难以理解的就是,编译的原理,为啥class program里面
再new一下自己的名字的实例,然后再调用方法呢?这不是嵌套了吗?
using System;
namespace callmethod
{
class Program
{
static void Main(string[] args)
{
//直接调用的系统命名空间,Console下的WriteLine方法
Console.WriteLine("Hello World!");
//PrintDateAndTime(); 直接调用错误的
}
void PrintDateAndTime()
{
DateTime dt = DateTime.Now;
Console.WriteLine($"{dt}");
}
}
}
局部函数:
Local Functions
As just explained, the code inside a method block can call another method. If that other method is in the
same class, it can be called simply by using its name and passing any required parameters (described in the
next section). If that method is in another class, it must generally be called by using an object instance of the
other class. Methods in other classes also must have been declared using the public access modifier.
Beginning with C# 7.0 you can declare a separate method directly inside another method. This isolates
the contained method from other code as it can only be called from within the method in which it is
contained. When used properly, this can also lead to clearer code and easier maintenance. These contained
methods are called local functions.
Unlike local variables, which must be declared before they can be used, you can declare a local function
at any point within its containing method.
The following code shows an example of a method called MethodWithLocalFunction that contains a
local function called MyLocalFunction.
using System;
class MyClass
{
public int Sum( int x, int y ) // Declare the method.
{
return x + y; // Return the sum.
}
public float Avg( float input1, float input2 ) // Declare the method.
{
return ( input1 + input2 ) / 2.0F; // Return the average.
}
}
class Program
{
static void Main()
{
MyClass myT = new MyClass();
int someInt = 6;
Console.WriteLine( "Newsflash: Sum: {0} and {1} is {2}", 5, someInt, myT.Sum( 5, someInt ) ); // Invoke the method.
Console.WriteLine( "Newsflash: Avg: {0} and {1} is {2}", 5, someInt, myT.Avg( 5, someInt ) ); // Invoke the method.
}
}
调用之前
调用之前 a1 和 a2 都是实参,所以入栈stack,只是因为a1是类,所以入栈的是a1的引用
方法开始:
方法开始,f1和f2是形参,也入栈了。只是有一点,f1=a1之后其实是赋值了一个引用。所以指向的都是同一个堆的数据 val = 20
方法结束后,a1和a2是实参,所以数值不变,而f2的值变成了15,f1和a1一样是引用,也不变。只是他们指向的堆heap的值变成了25
方法之后,f1和f2被出栈pop掉,所以
接下去讲引用参数,ref
- 使用ref,两边都要加上ref ,在实参和形参都需要
- 实参必须是变量,在用作实参前必须被赋值。如果是引用类型,赋值为一个引用或者null
对于值参数,系统在栈上为形参分配内存。类似做一份拷贝。只是由于引用类型本身是引用,虽然拷贝了,但是指向的堆数据还是一样的。
而对于ref参数(引用参数),系统并不给形参分配内存,我估计编译器只是做了一下赋值,并且关联了别名。指向相同的内存位置(heap)
后果,就是实参和形参是联动的,最终结果一个改了 ,都会改。一个变化,都变化。
混合值引用
Ref 的情况如何呢?
Out 输出参数
实际上高级语言的特征之一,就是越来越复杂,美其名曰:优秀的语言。
Out参数理解为:反向。
之前ref,的主动权好比都在实参那边,实参传递过去,让形参和实参共享内存。把形参变成是实参的别名。
现在out,的主动权好比都在形参那边,被调用的方法里面把形参进行赋值或者其他运算操作之后,反哺给实参。
虽然本质上,out也是实参和形参共享内存,传递的路径不一样。反向。
C# 7.0以后的简便写法,符合逻辑(那么问题来了,你丫刚刚发明out的时候,你们这些专家死了吗?没想到吗?
所以,工程师永远不懂认知心理学,发明各种语言很多时候就是个笑话)
Parameter Arrays 数组参数
In the parameter types we've covered so far, there must be exactly one actual parameter for each formal parameter.
Parameter arrays are different in that they allow zero or more actual parameters of a particular type for a particular formal parameter.
在之前的章节中,参数类型必须是一个实参(actual parameter)对应一个 形参(formal parameter)
而数组参数Parameter Arrays确是不同的,它允许0个或多个实参对应一个特定类型或者一个特定的形参。
Important points about parameter arrays are the following:
要点如下:
• There can be only one parameter array in a parameter list.在一个参数列表中,list,只能有一个数组参数parameter array
• If there is one, it must be the last parameter in the list.如果有的话,这个数组参数也只能在这个list中的最后一个。
• All the parameters represented by the parameter array must be of the same type.由数组参数代表的参数都是同一个类型(这个是废话,数组的定义就是需要元素类型相同,elements same type)
To declare a parameter array, you must do the following:声明一个数组参数,要求如下:
• Use the params modifier before the data type.使用params修饰符 修饰数据类型
• Place a set of empty square brackets after the data type.在数据类型后放置一组空的中括号[]
The following method header shows the syntax for the declaration of a parameter array of type int.In this example, formal parameter inVals can represent zero or more actual int parameters
可选参数
顾名思义 参数是可选的 optional parameter
参数顺序