C# 是一个面向对象的编程语言,它是由微软(Microsoft)开发的,由 Ecma 和 ISO 核准认可的。C# 是专为公共语言基础结构(CLI)设计的。CLI 由可执行代码和运行时环境组成,允许在不同的计算机平台和体系结构上使用各种高级语言。
虽然 C# 的构想十分接近于传统高级语言 C 和 C++,是一门面向对象的编程语言,但是它与 Java 非常相似,有许多强大的编程功能,因此得到广大程序员的青睐。
下面列出 C# 一些重要的功能:
在这一章中,我们将讨论创建 C# 编程所需的工具。我们已经提到 C# 是 .Net 框架的一部分,且用于编写 .Net 应用程序。因此,在讨论运行 C# 程序的可用工具之前,让我们先了解一下 C# 与 .Net 框架之间的关系。
.Net 框架是一个创新的平台,能帮您编写出下面类型的应用程序:
.Net 框架应用程序是多平台的应用程序。框架的设计方式使它适用于下列各种语言:C#、C++、Visual Basic、Jscript、COBOL 等等。所有这些语言可以访问框架,彼此之间也可以互相交互。
.Net 框架由一个巨大的代码库组成,用于 C# 等客户端语言。下面列出一些 .Net 框架的组件:
如需了解每个组件的详细信息,请参阅微软(Microsoft)的文档。
微软(Microsoft)提供了下列用于 C# 编程的开发工具:
Visual Studio 2019 (VS) (推荐)


虽然 .NET 框架是运行在 Windows 操作系统上,但是也有一些运行于其它操作系统上的版本可供选择。Mono 是 .NET 框架的一个开源版本,它包含了一个 C# 编译器,且可运行于多种操作系统上,比如各种版本的 Linux 和 Mac OS。
下载地址:https://www.mono-project.com/download/stable/

在我们学习 C# 编程语言的基础构件块之前,让我们先看一下 C# 的最小的程序结构,以便作为接下来章节的参考。
一个 C# 程序主要包括以下部分:
C# 文件的后缀为 .cs 。
以下创建一个HelloWorld.cs 文件,文件包含了可以打印出 “Hello World” 的简单代码:
using System;
namespace HelloWorldApplication
{
class HelloWorld
{
static void Main(string[] args)
{
/* 我的第一个 C# 程序*/
Console.WriteLine("Hello World");
Console.ReadKey();
}
}
}
以下几点值得注意:
让我们来看看一个 CarApplication(车)类的实现,并借此讨论 C# 的基本语法:
using System;
namespace CarApplication
{
class Car
{
// 成员变量
string color;
double price;
public void Run()
{
Console.WriteLine("车已经动起来了");
}
}
class ExecuteCar
{
static void Main(string[] args)
{
CarApplication car = new CarApplication();
car.Run();
Console.ReadLine();
}
}
}
在任何 C# 程序中的第一条语句都是:
using System;
using 关键字用于在程序中包含命名空间。一个程序可以包含多个 using 语句。
class 关键字用于声明一个类。
注释是用于解释代码。编译器会忽略注释的条目。在 C# 程序中,多行注释以 /* 开始,并以字符 / 终止,如下所示:
/ This program demonstrates The basic syntax of C# programming Language */
单行注释是用 ‘//’ 符号表示。例如:
//end class Rectangle
变量是类的属性或数据成员,用于存储数据。在上面的程序中,Rectangle 类有两个成员变量,名为 length 和 width。
函数是一系列执行指定任务的语句。类的成员函数是在类内声明的。我们举例的类 Rectangle 包含了三个成员函数:_ AcceptDetails_、GetArea 和 Display。
关键字是 C# 编译器预定义的保留字。这些关键字不能用作标识符,但是,如果您想使用这些关键字作为标识符,可以在关键字前面加上 @ 字符作为前缀。
在 C# 中,有些关键字在代码的上下文中有特殊的意义,如 get 和 set,这些被称为上下文关键字(contextual keywords)。
下表列出了 C# 中的保留关键字(Reserved Keywords)和上下文关键字(Contextual Keywords):
| 保留关键字 | ||||||
|---|---|---|---|---|---|---|
| abstract | as | base | bool | break | byte | case |
| catch | char | checked | class | const | continue | decimal |
| default | delegate | do | double | else | enum | event |
| explicit | extern | false | finally | fixed | float | for |
| foreach | goto | if | implicit | in | in (generic modifier) | int |
| interface | internal | is | lock | long | namespace | new |
| null | object | operator | out | out (generic modifier) | override | params |
| private | protected | public | readonly | ref | return | sbyte |
| sealed | short | sizeof | stackalloc | static | string | struct |
| switch | this | throw | true | try | typeof | uint |
| ulong | unchecked | unsafe | ushort | using | virtual | void |
| volatile | while | |||||
| 上下文关键字 | ||||||
| add | alias | ascending | descending | dynamic | from | get |
| global | group | into | join | let | orderby | partial (type) |
| partial (method) | remove | select | set |
值类型变量可以直接分配给一个值。它们是从类 System.ValueType 中派生的。
值类型直接包含数据。比如 int、char、float,它们分别存储数字、字符、浮点数。当您声明一个 int 类型时,系统分配内存来存储值。
下表列出了 C# 2010 中可用的值类型:

如需得到一个类型或一个变量在特定平台上的准确尺寸,可以使用 sizeof 方法。表达式 sizeof(type) 产生以字节为单位存储对象或类型的存储尺寸。下面举例获取任何机器上 int 类型的存储尺寸:
using System;
namespace DataTypeApplication
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Size of int: {0}", sizeof(int));
Console.ReadLine();
}
}
}
引用类型不包含存储在变量中的实际数据,但它们包含对变量的引用。
换句话说,它们指的是一个内存位置。使用多个变量时,引用类型可以指向一个内存位置。如果内存位置的数据是由一个变量改变的,其他变量会自动反映这种值的变化。内置的 引用类型有:object、dynamic 和 string。
对象(Object)类型 是 C# 通用类型系统(Common Type System - CTS)中所有数据类型的终极基类。Object 是 System.Object 类的别名。所以对象(Object)类型可以被分配任何其他类型(值类型、引用类型、预定义类型或用户自定义类型)的值。但是,在分配值之前,需要先进行类型转换。
当一个值类型转换为对象类型时,则被称为 装箱;另一方面,当一个对象类型转换为值类型时,则被称为 拆箱。
object obj; obj = 100; // 这是装箱
您可以存储任何类型的值在动态数据类型变量中。这些变量的类型检查是在运行时发生的。
声明动态类型的语法:
dynamic <variable_name> = value;
例如:
dynamic d = 20;
动态类型与对象类型相似,但是对象类型变量的类型检查是在编译时发生的,而动态类型变量的类型检查是在运行时发生的。
字符串(String)类型 允许您给变量分配任何字符串值。字符串(String)类型是 System.String 类的别名。它是从对象(Object)类型派生的。字符串(String)类型的值可以通过两种形式进行分配:引号和 @引号。
指针类型变量存储另一种类型的内存地址。C# 中的指针与 C 或 C++ 中的指针有相同的功能。
声明指针类型的语法:
type* identifier;
例如:
char* cptr; int* iptr;
类型转换从根本上说是类型铸造,或者说是把数据从一种类型转换为另一种类型。在 C# 中,类型铸造有两种形式:
下面的实例显示了一个显式的类型转换:
namespace TypeConversionApplication
{
class ExplicitConversion
{
static void Main(string[] args)
{
double d = 5673.74;
int i;
// 强制转换 double 为 int
i = (int)d;
Console.WriteLine(i);
Console.ReadKey();
}
}
}
C# 提供了下列内置的类型转换方法:
| 序号 | 方法 & 描述 |
|---|---|
| 1 | ToBoolean 如果可能的话,把类型转换为布尔型。 |
| 2 | ToByte 把类型转换为字节类型。 |
| 3 | ToChar 如果可能的话,把类型转换为单个 Unicode 字符类型。 |
| 4 | ToDateTime 把类型(整数或字符串类型)转换为 日期-时间 结构。 |
| 5 | ToDecimal 把浮点型或整数类型转换为十进制类型。 |
| 6 | ToDouble 把类型转换为双精度浮点型。 |
| 7 | ToInt16 把类型转换为 16 位整数类型。 |
| 8 | ToInt32 把类型转换为 32 位整数类型。 |
| 9 | ToInt64 把类型转换为 64 位整数类型。 |
| 10 | ToSbyte 把类型转换为有符号字节类型。 |
| 11 | ToSingle 把类型转换为小浮点数类型。 |
| 12 | ToString 把类型转换为字符串类型。 |
| 13 | ToType 把类型转换为指定类型。 |
| 14 | ToUInt16 把类型转换为 16 位无符号整数类型。 |
| 15 | ToUInt32 把类型转换为 32 位无符号整数类型。 |
| 16 | ToUInt64 把类型转换为 64 位无符号整数类型。 |
一个变量只不过是一个供程序操作的存储区的名字。在 C# 中,每个变量都有一个特定的类型,类型决定了变量的内存大小和布局。范围内的值可以存储在内存中,可以对变量进行一系列操作。
我们已经讨论了各种数据类型。C# 中提供的基本的值类型大致可以分为以下几类:
| 类型 | 举例 |
|---|---|
| 整数类型 | sbyte、byte、short、ushort、int、uint、long、ulong 和 char |
| 浮点型 | float 和 double |
| 十进制类型 | decimal |
| 布尔类型 | true 或 false 值,指定的值 |
| 空类型 | 可为空值的数据类型 |
C# 允许定义其他值类型的变量,比如 enum,也允许定义引用类型变量,比如 class。这些我们将在以后的章节中进行讨论。在本章节中,我们只研究基本变量类型。
C# 中变量定义的语法:
<data_type> <variable_list>;
在这里,data_type 必须是一个有效的 C# 数据类型,可以是 char、int、float、double 或其他用户自定义的数据类型。variable_list 可以由一个或多个用逗号分隔的标识符名称组成。
一些有效的变量定义如下所示:
int i, j, k; char c, ch; float f, salary; double d;
您可以在变量定义时进行初始化:
int i = 100;
变量通过在等号后跟一个常量表达式进行初始化(赋值)。初始化的一般形式为:
variable_name = value;
变量可以在声明时被初始化(指定一个初始值)。初始化由一个等号后跟一个常量表达式组成,如下所示:
<data_type> <variable_name> = value;
一些实例:
int d = 3, f = 5; /* 初始化 d 和 f. */
byte z = 22; /* 初始化 z. */
double pi = 3.14159; /* 声明 pi 的近似值 */
char x = 'x'; /* 变量 x 的值为 'x' */
常量是固定值,程序执行期间不会改变。常量可以是任何基本数据类型,比如整数常量、浮点常量、字符常量或者字符串常量,还有枚举常量。
常量可以被当作常规的变量,只是它们的值在定义后不能被修改。
整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,没有前缀则表示十进制。
整数常量也可以有后缀,可以是 U 和 L 的组合,其中,U 和 L 分别表示 unsigned 和 long。后缀可以是大写或者小写,多个后缀以任意顺序进行组合。
这里有一些整数常量的实例:
212 /* 合法 / 215u / 合法 / 0xFeeL / 合法 / 078 / 非法:8 不是一个八进制数字 / 032UU / 非法:不能重复后缀 */
以下是各种类型的整数常量的实例:
85 /* 十进制 / 0213 / 八进制 / 0x4b / 十六进制 / 30 / int / 30u / 无符号 int / 30l / long / 30ul / 无符号 long */
一个浮点常量是由整数部分、小数点、小数部分和指数部分组成。您可以使用小数形式或者指数形式来表示浮点常量。
这里有一些浮点常量的实例:
3.14159 /* 合法 / 314159E-5L / 合法 / 510E / 非法:不完全指数 / 210f / 非法:没有小数或指数 / .e55 / 非法:缺少整数或小数 */
使用浮点形式表示时,必须包含小数点、指数或同时包含两者。使用指数形式表示时,必须包含整数部分、小数部分或同时包含两者。有符号的指数是用 e 或 E 表示的。
字符常量是括在单引号里,例如,‘x’,且可存储在一个简单的字符类型变量中。一个字符常量可以是一个普通字符(例如 ‘x’)、一个转义序列(例如 ‘\t’)或者一个通用字符(例如 ‘\u02C0’)。
在 C# 中有一些特定的字符,当它们的前面带有反斜杠时有特殊的意义,可用于表示换行符(\n)或制表符 tab(\t)。在这里,列出一些转义序列码:
| 转义序列 | 含义 |
|---|---|
| \\ | \ 字符 |
| \’ | ’ 字符 |
| \" | " 字符 |
| \? | ? 字符 |
| \a | Alert 或 bell |
| \b | 退格键(Backspace) |
| \f | 换页符(Form feed) |
| \n | 换行符(Newline) |
| \r | 回车 |
| \t | 水平制表符 tab |
| \v | 垂直制表符 tab |
| \ooo | 一到三位的八进制数 |
| \xhh . . . | 一个或多个数字的十六进制数 |
字符串常量是括在双引号 “” 里,或者是括在 @"" 里。字符串常量包含的字符与字符常量相似,可以是:普通字符、转义序列和通用字符
使用字符串常量时,可以把一个很长的行拆成多个行,可以使用空格分隔各个部分。
这里是一些字符串常量的实例。下面所列的各种形式表示相同的字符串。
string a = "hello, world"; // hello, world
string b = @"hello, world"; // hello, world
string c = "hello \t world"; // hello world
string d = @"hello \t world"; // hello \t world
string e = "Joe said \"Hello\" to me"; // Joe said "Hello" to me
string f = @"Joe said ""Hello"" to me"; // Joe said "Hello" to me
string g = "\\\\server\\share\\file.txt"; // \\server\share\file.txt
string h = @"\\server\share\file.txt"; // \\server\share\file.txt
string i = "one\r\ntwo\r\nthree";
string j = @"one
two
three";
常量是使用 const 关键字来定义的 。定义一个常量的语法如下:
const <data_type> <constant_name> = value;
运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C# 有丰富的内置运算符,分类如下:
算术运算符
关系运算符
逻辑运算符
位运算符
赋值运算符
其他运算符
。
| 运算符 | 描述 |
|---|---|
| + | 把两个操作数相加 |
| - | 从第一个操作数中减去第二个操作数 |
| * | 把两个操作数相乘 |
| / | 分子除以分母 |
| % | 取模运算符,整除后的余数 |
| ++ | 自增运算符,整数值增加 1 |
| – | 自减运算符,整数值减少 1 |
| 运算符 | 描述 |
|---|---|
| == | 检查两个操作数的值是否相等,如果相等则条件为真。 |
| != | 检查两个操作数的值是否相等,如果不相等则条件为真。 |
| > | 检查左操作数的值是否大于右操作数的值,如果是则条件为真。 |
| < | 检查左操作数的值是否小于右操作数的值,如果是则条件为真。 |
| >= | 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。 |
| <= | 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。 |
| 运算符 | 描述 |
|---|---|
| && | 称为逻辑与运算符。如果两个操作数都非零,则条件为真。 |
| || | 称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。 |
| ! | 称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。 |
前提:
假设如果 A = 60,且 B = 13,现在以二进制格式表示,它们如下所示:
A = 0011 1100
B = 0000 1101
| 运算符 | 描述 | 实例 |
|---|---|---|
| & | 如果同时存在于两个操作数中,二进制 AND 运算符复制一位到结果中。 | (A & B) 将得到 12,即为 0000 1100 |
| | | 如果存在于任一操作数中,二进制 OR 运算符复制一位到结果中。 | (A | B) 将得到 61,即为 0011 1101 |
| ^ | 如果存在于其中一个操作数中但不同时存在于两个操作数中,二进制异或运算符复制一位到结果中。 | (A ^ B) 将得到 49,即为 0011 0001 |
| ~ | 按位取反运算符是一元运算符,具有"翻转"位效果,即0变成1,1变成0,包括符号位。 | (~A ) 将得到 -61,即为 1100 0011,一个有符号二进制数的补码形式。 |
| << | 二进制左移运算符。左操作数的值向左移动右操作数指定的位数。 | A << 2 将得到 240,即为 1111 0000 |
| >> | 二进制右移运算符。左操作数的值向右移动右操作数指定的位数。 | A >> 2 将得到 15,即为 0000 1111 |
| 语句 | 描述 |
|---|---|
| if 语句 | 一个 if 语句 由一个布尔表达式后跟一个或多个语句组成。 |
| if…else 语句 | 一个 if 语句 后可跟一个可选的 else 语句,else 语句在布尔表达式为假时执行。 |
| 嵌套 if 语句 | 您可以在一个 if 或 else if 语句内使用另一个 if 或 else if 语句。 |
| switch 语句 | 一个 switch 语句允许测试一个变量等于多个值时的情况。 |
| 嵌套 switch 语句 | 您可以在一个 switch 语句内使用另一个 **switch **语句。 |
实例:
switch (Condition_Value) {
case Val01:
//coding
break;
case Val02:
//coding
break;
default:
//coding
break;
}; |
使用运算符来简化if…else语句。
Exp1 ? Exp2 : Exp3;
其中,Exp1、Exp2 和 Exp3 是表达式。代表着如果Exp1为true ,Exp2成立,反之则Exp3成立。
有时候,我们需要多次执行同一块代码。
图解:
| 循环类型 | 描述 |
|---|---|
| while 循环 | 当给定条件为真时,重复语句或语句组。它会在执行循环主体之前测试条件。 |
| for/foreach 循环 | 多次执行一个语句序列,简化管理循环变量的代码。 |
| do…while 循环 | 除了它是在循环主体结尾测试条件外,其他与 while 语句类似。 |
| 嵌套循环 | 您可以在 while、for 或 do…while 循环内使用一个或多个循环。 |
循环控制语句更改执行的正常序列。当执行离开一个范围时,所有在该范围中创建的自动对象都会被销毁。
| 控制语句 | 描述 |
|---|---|
| break 语句 | 终止 loop 或 switch 语句,程序流将继续执行紧接着 loop 或 switch 的下一条语句。 |
| continue 语句 | 引起循环跳过主体的剩余部分,立即重新开始测试条件。 |
一个方法是把一些相关的语句组织在一起,用来执行一个任务的语句块。每一个 C# 程序至少有一个带有 Main 方法的类。
要使用一个方法,您需要:
当定义一个方法时,从根本上说是在声明它的结构的元素。在 C# 中,定义方法的语法如下:
(Parameter List) { Method Body }
下面是方法的各个元素:
Access Specifier:访问修饰符,这个决定了变量或方法对于另一个类的可见性。
Return type:返回类型,一个方法可以返回一个值。返回类型是方法返回的值的数据类型。如果方法不返回任何值,则返回类型为 void。
Method name:方法名称,是一个唯一的标识符,且是大小写敏感的。它不能与类中声明的其他标识符相同。
Parameter list:参数列表,使用圆括号括起来,该参数是用来传递和接收方法的数据。参数列表是指方法的参数类型、顺序和数量。参数是可选的,也就是说,一个方法可能不包含参数。
Method body:方法主体,包含了完成任务所需的指令集。
当调用带有参数的方法时,您需要向方法传递参数。在 C# 中,有三种向方法传递参数的方式:
| 方式 | 描述 |
|---|---|
| 值参数 | 这种方式复制参数的实际值给函数的形式参数,实参和形参使用的是两个不同内存中的值。 |
| 引用参数 | 这种方式复制参数的内存位置的引用给形式参数。这意味着,当形参的值发生改变时,同时也改变实参的值。 |
| 输出参数 | 这种方式可以返回多个值。 |
? 单问号用于对 int、double、bool 等无法直接赋值为 null 的数据类型进行 null 的赋值,意思是这个数据类型是 Nullable 类型的。
int? i = 3;
等同于:
Nullable i = new Nullable(3);
int i; //默认值0
int? ii; //默认值null
?? 双问号用于判断一个变量在为 null 的时候返回一个指定的值。
接下来我们详细说明。
C# 提供了一个特殊的数据类型,nullable 类型(可空类型),可空类型可以表示其基础值类型正常范围内的值,再加上一个 null 值。
声明一个 nullable 类型(可空类型)的语法如下:
< data_type> ? <variable_name> = null;
数组是一个存储相同类型元素的固定大小的顺序集合。
所有的数组都是由连续的内存位置组成的。最低的地址对应第一个元素,最高的地址对应最后一个元素。
datatype[] arrayName;
datatype 用于指定被存储在数组中的元素的类型。
[ ] 指定数组的维度。
arrayName 指定数组的名称。
声明一个数组不会在内存中初始化数组。数组是一个引用类型,所以您需要使用 new 关键字来创建数组的实例。
例如:
double[] balance = new double[10];
实例:
**double[] balance = new double[10]; **
double[] balance = { 2340.0, 4523.69, 3421.0};
int [] marks = new int[5] { 99, 98, 92, 97, 95};
通过索引(下标)来访问数组元素:
例如:
double salary = balance[9];
在 C# 中,您可以使用字符数组来表示字符串,但是,更常见的做法是使用 string 关键字来声明一个字符串变量。
| 序号 | 属性名称 & 描述 |
|---|---|
| 2 | Length 在当前的 String 对象中获取字符数。 |
| 方法名称 & 描述 |
|---|
| **public static string Concat( string str0, string str1 ) ** 连接两个 string 对象。 |
| **public bool Contains( string value ) ** 返回一个表示指定 string 对象是否出现在字符串中的值。 |
| **public bool EndsWith( string value ) ** 判断 string 对象的结尾是否匹配指定的字符串。 |
| **public bool Equals( string value ) ** 判断当前的 string 对象是否与指定的 string 对象具有相同的值。 |
| **public static string Format( string format, Object arg0 ) ** 把指定字符串中一个或多个格式项替换为指定对象的字符串表示形式。 |
| **public int IndexOf( char value ) ** 返回指定 Unicode 字符在当前字符串中第一次出现的索引,索引从 0 开始。 |
| public char[] ToCharArray() 返回一个带有当前 string 对象中所有字符的 Unicode 字符数组。 |

(结构体和枚举 放入一章)
在 C# 中,结构体是值类型数据结构。它使得一个单一变量可以存储各种数据类型的相关数据。struct 关键字用于创建结构体。
为了定义一个结构体,您必须使用 struct 语句。struct 语句为程序定义了一个带有多个成员的新的数据类型。
实例:
struct Books { public string Name; public string Author; };
— 学完类 和接口 再来说这个
C# 中的结构有以下特点:
结构可带有方法、字段、索引、属性、运算符方法和事件。
结构可定义构造函数,但不能定义析构函数。
与类不同,结构不能继承其他的结构或类。
结构可实现一个或多个接口。
结构成员不能指定为 abstract、virtual 或 protected。
当您使用 New 操作符创建一个结构对象时,会调用适当的构造函数来创建结构。与类不同,结构可以不使用 New 操作符即可被实例化。
如果不使用 New 操作符,只有在所有的字段都被初始化之后,字段才被赋值,对象才被使用。
枚举是一组命名整型常量。枚举类型是使用 enum 关键字声明的。
C# 枚举是值类型。但它不能继承。
语法:
enum <enum_name> { enumeration list };
其中,
默认情况下,第一个枚举符号的值是 0.以此类推。
enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };
类的定义是以关键字 class 开始,后跟类的名称。类的主体,包含在一对花括号内。下面是类定义的一般形式:
<access specifier> class class_name { // member variables <access specifier> <data type> variable1; <access specifier> <data type> variable2; ... <access specifier> <data type> variableN; // member methods <access specifier> <return type> method1(parameter_list) { // method body } <access specifier> <return type> method2(parameter_list) { // method body } ... <access specifier> <return type> methodN(parameter_list) { // method body }}
成员变量 ==》 成员变量是对象的属性
成员方法(函数)=》实现具体功能的代码
类的 构造函数 是类的一个特殊的成员函数,当创建类的新对象时执行。
构造函数的名称与类的名称完全相同,它没有任何返回类型。
using System;namespace CarApplication{ class Car { private string carName; // 车名 public Car() { Console.WriteLine("对象已创建"); } public void setCarName( string name ) { carName = name; } public string getCarName() { return carName; } static void Main(string[] args) { Car car = new Car(); // 设置车子的名称 car.setLength("比亚迪"); Console.WriteLine("车名为: {0}", line.getCarName()); Console.ReadKey(); } }}
我们可以使用 static 关键字把类成员定义为静态的。当我们声明一个类成员为静态时,意味着无论有多少个类的对象被创建,只会有一个该静态成员的副本。
分类: 静态变量 和 静态函数(方法)
调用方式: 类名.静态成员名称 或 类名.静态函数名称
类的 析构函数 是类的一个特殊的成员函数,当类的对象超出范围时执行。
析构函数的名称是在类的名称前加上一个波浪形(~)作为前缀,它不返回值,也不带任何参数。
析构函数用于在结束程序(比如关闭文件、释放内存等)之前释放资源。析构函数不能继承或重载。
using System;namespace CarApplication{ class Car { private string carName; // 车名 public Car() { Console.WriteLine("对象已创建"); }private string name; // 线条的长度 public Car() // 构造函数 { Console.WriteLine("对象已创建"); } ~Car() //析构函数 { Console.WriteLine("对象已删除"); } public void setCarName( string name ) { carName = name; } public string getCarName() { return carName; } static void Main(string[] args) { Car car = new Car(); // 设置车子的名称 car.setLength("比亚迪"); Console.WriteLine("车名为: {0}", line.getCarName()); Console.ReadKey(); } }}
一个 访问修饰符 定义了一个类成员的范围和可见性。
(仅家族人士有权限 或者 仅自己和子孙有权限)
abstract class Class_Name{
}
1.方法可以不用实现。(意味着方法体不需要)
2.可以被继承
继承允许我们根据一个类来定义另一个类,这使得创建和维护应用程序变得更容易。同时也有利于重用代码和节省开发时间。
一个类可以派生自多个类或接口,这意味着它可以从多个基类或接口继承数据和函数。
C# 中创建派生类的语法如下:
<访问修饰符> class <基类>
{
…
}
class <派生类> : <基类>
{
…
}
派生类继承了基类的成员变量和成员方法。因此父类对象应在子类对象创建之前被创建。您可以在成员初始化列表中进行父类的初始化。
多重继承指的是一个类别可以同时从多于一个父类继承行为与特征的功能。与单一继承相对,单一继承指一个类别只可以继承自一个父类。
C# 不支持多重继承。但是,您可以使用接口来实现多重继承。
— 方法重载和重写(归于一章)
方法(函数)重载:
多态是同一个行为具有多个不同表现形式或形态的能力。
多态性意味着有多重形式。
属性(Property) 是类(class)、结构(structure)和接口(interface)的命名(named)成员。
// 方式一//首先定义成员变量(也可以成字段)private <data_type> <variable_name>;//再定义属性 public <data_type> <prop_name> { get { return <variable_name>; } set { <variable_name> = value; } } //方式二public <data_type> <prop_name> { get; set; }
接口定义了属性、方法和事件,这些都是接口的成员。接口只包含了成员的声明。成员的定义是派生类的责任。抽象类在某种程度上与接口类似,但是,它们大多是由基类的派生类。
interface <Interface_Name>{ //数据类型 变量名称--(成员函数) <data_type> variable_name(); // 函数(方法)名称 void Method_Name();}
1.接口本身并不实现任何功能。
2.抽象类不能直接实例化。
示例:
interface MyInterface{ void Play();}class InterfaceImplementer : MyInterface{ public void Play() { Console.WriteLine("此处是实现接口的方法(函数)"); }}
正则表达式 是一种匹配输入文本的模式。
| 转义字符 | 描述 | 模式 | 匹配 |
|---|---|---|---|
| \a | 与报警 (bell) 符 \u0007 匹配。 | \a | “Warning!” + ‘\u0007’ 中的 “\u0007” |
| \b | 在字符类中,与退格键 \u0008 匹配。 | [\b]{3,} | “\b\b\b\b” 中的 “\b\b\b\b” |
| \t | 与制表符 \u0009 匹配。 | (\w+)\t | “Name\tAddr\t” 中的 “Name\t” 和 “Addr\t” |
| \r | 与回车符 \u000D 匹配。(\r 与换行符 \n 不是等效的。) | \r\n(\w+) | “\r\nHello\nWorld.” 中的 “\r\nHello” |
| \v | 与垂直制表符 \u000B 匹配。 | [\v]{2,} | “\v\v\v” 中的 “\v\v\v” |
| \f | 与换页符 \u000C 匹配。 | [\f]{2,} | “\f\f\f” 中的 “\f\f\f” |
| \n | 与换行符 \u000A 匹配。 | \r\n(\w+) | “\r\nHello\nWorld.” 中的 “\r\nHello” |
| 更多… |
| 表达式 | 描述 |
|---|---|
| \d | 代表数字0-9 |
| [0-9] | 代表数字0-9,跟\d是一样的表示 |
| \w | 代表字母 |
| \W | 与任何非单词字符匹配。 |
| \s | 与任何空白字符匹配。 |
| \S | 与任何非空白字符匹配。 |
| $ | 匹配必须出现在字符串的末尾。 |
| 更多… |
异常是在程序执行期间出现的问题。C# 中的异常是对程序运行时出现的特殊情况的一种响应
try{ // 存在引起异常的语句}catch( ExceptionName e2 ){ // 错误处理代码}catch( ExceptionName eN ){ // 错误处理代码}finally{ // 要执行的语句}
| 异常类 | 描述 |
|---|---|
| System.IO.IOException | 处理 I/O 错误。 |
| System.IndexOutOfRangeException | 处理当方法指向超出范围的数组索引时生成的错误。 |
| System.OutOfMemoryException | 处理空闲内存不足生成的错误。 |
| System.StackOverflowException | 处理栈溢出生成的错误。 |
| 更多… |
示例:
##ApplicationException 就是应用里的异常public class MyException: ApplicationException{ public MyException(string message): base(message) { }}//throw (new MyException("我是个异常"));
当打开文件进行读写时,它变成一个**流(Stream)。**从根本上说,流是通过通信路径传递的字节序列。有两个主要的流:输入流 和 输出流。输入流用于从文件读取数据(读操作),输出流用于向文件写入数据(写操作)。
文件创建、删除、写入数据、读取数据
//第一种方式 //创建或打开用于写入 UTF-8 编码文本的文件。 如果该文件已存在,将覆盖其内容。 //返回 一个 System.IO.StreamWriter,它使用 UTF-8 编码写入到指定的文件。 StreamWriter streamWriter1 = File.CreateText(path);//执行完毕--需要关闭streamWriter1.Close();//第二种方式//在指定路径中创建或覆盖文件。FileStream fileStream = File.Create(path);//执行完毕--需要关闭fileStream.Close();//第三种方式FileInfo file = new FileInfo(path);FileStream fileStream = file.Create();
//第一种方式FileInfo file = new FileInfo(path);if (file.Exists){ file.Delete();}//第二种方式 if (File.Exists(path)) { File.Delete(path); }
FileInfo file = new FileInfo(@"C:\Users\lenovo\Desktop\myTxt.txt"); FileStream fileStream = file.Create(); string str = "我在学习File"; byte[] decBytes = System.Text.Encoding.UTF8.GetBytes(str); fileStream.Write(decBytes, 0, decBytes.Length); fileStream.Close();
try { FileInfo file = new FileInfo(@"C:\Users\lenovo\Desktop\big.pdf"); using (FileStream fsSource = file.OpenRead()) { // 将这个文件转化成字节数组-bytes byte[] bytes = new byte[fsSource.Length]; int numBytesToRead = (int)fsSource.Length; int numBytesRead = 0; while (numBytesToRead > 0) { //从流中读取字节块并将该数据写入给定缓冲区中。 //=》作用是 把内容 写到bytes里面 int n = fsSource.Read(bytes, numBytesRead, numBytesToRead); //返回结果: //读入缓冲区中的总字节数。 当缓存字节归零时 中断这个(读)循环 if (n == 0) { break; } numBytesRead += n; numBytesToRead -= n; } string str = System.Text.Encoding.UTF8.GetString(bytes); Console.WriteLine("file content: " + str); } } catch (Exception ex) { throw; }
包含定义各种对象集合(如列表、队列、位数组、哈希表和字典)的接口和类。
| ArrayList | 使用大小会根据需要动态增加的数组来实现 IList 接口。 |
|---|---|
| BitArray | 管理位值的压缩数组,这些值以布尔值的形式表示,其中 true 表示此位为开 (1),false 表示此位为关 (0)。 |
| CaseInsensitiveComparer | 比较两个对象是否相等,比较时忽略字符串的大小写。 |
| CaseInsensitiveHashCodeProvider | 使用忽略字符串大小写的哈希算法,为对象提供哈希代码。 |
| CollectionBase | 提供强类型集合的 abstract 基类。 |
| Comparer | 比较两个对象是否相等,其中字符串比较是区分大小写的。 |
| DictionaryBase | 为键/值对的强类型集合提供 abstract 基类。 |
| Hashtable | 表示根据键的哈希代码进行组织的键/值对的集合。 |
| Queue | 表示对象的先进先出集合。 |
| ReadOnlyCollectionBase | 提供强类型化非泛型只读集合的 abstract 基类。 |
| SortedList | 表示键/值对的集合,这些键值对按键排序并可按照键和索引访问。 |
| Stack | 表示对象的简单后进先出 (LIFO) 非泛型集合。 |
| StructuralComparisons | 提供用于执行两个集合对象的结构化比较的对象。 |
| 表示 Dictionary<TKey,TValue> 中密钥的集合。 此类不能被继承。 |



List 、Dictionary的使用(它们都属于System.Collections.Generic这个命名空间)

泛型(Generic) 允许您延迟编写类或方法中的编程元素的数据类型的规范,直到实际在程序中使用它的时候。换句话说,泛型允许您编写一个可以与任何数据类型一起工作的类或方法。
使用泛型是一种增强程序功能的技术,主要体现在以下几个方面:
在声明泛型方法/泛型类的时候,可以给泛型加上一定的约束来满足我们特定的一些条件。
public class class_name <T> where T : new(){}
public class class_name<T> where T : base_class_name{}
特性(Attribute)是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。
[attribute(positional_parameters, name_parameter = value, …)] element
.Net 框架提供了三种预定义特性:
预定义特性 AttributeUsage 描述了如何使用一个自定义特性类。它规定了特性可应用到的项目的类型。
规定该特性的语法如下:
[AttributeUsage( validon, AllowMultiple=allowmultiple, Inherited=inherited )]
其中:
这个预定义特性标记了一个条件方法,其执行依赖于指定的预处理标识符。
它会引起方法调用的条件编译,取决于指定的值,比如 Debug 或 Trace。例如,当调试代码时显示变量的值。
规定该特性的语法如下:
[Conditional( conditionalSymbol )]
例如:
[Conditional(“DEBUG”)]
这个预定义特性标记了不应被使用的程序实体。它可以让您通知编译器丢弃某个特定的目标元素。例如,当一个新方法被用在一个类中,但是您仍然想要保持类中的旧方法,您可以通过显示一个应该使用新方法,而不是旧方法的消息,来把它标记为 obsolete(过时的)。
规定该特性的语法如下:
[Obsolete( message )] [Obsolete( message, iserror )]
其中:
反射指程序可以访问、检测和修改它本身状态或行为的一种能力。我们可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。
优点:
缺点:
反射(Reflection)有下列用途:
C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。委托(Delegate)特别用于实现事件和回调方法。
delegate ;
delegate <return type> <delegate-name> <parameter list>;<delegate-name> dg = new <delegate-name>(匹配的方法放入此处);
<variable_name>= delegate(int x) { //coding };
类似代理功能,拥有多态性,相同委托可以合并 并按顺序执行。
事件(Event) 基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些提示信息,如系统生成的通知。应用程序需要在事件发生时响应事件。例如,中断。
C# 中使用事件机制实现线程间的通信。
类 或对象可以通过事件向其他类或对象通知发生的相关事情。 发送(或引发)事件的类称为“发布者”,接收(或处理)事件的类称为“订阅者”。
在类的内部声明事件,首先必须声明该事件的委托类型。
关键字: event
// 基于上面的委托定义事件
public event <event_name>;
事件具有以下属性:
using System;namespace ConsoleApp1{ class CarEvent { //默认速度 private int speed =80; //警告速度 private int Warn_Speed =100; public delegate void Exceed_Speed_Limit_Even(); //基于上面的委托定义事件 public event Exceed_Speed_Limit_Even Exceed_Speed_Even; static void Main() { CarEvent carEvent = new CarEvent(); carEvent.Exceed_Speed_Even += Speed_Limit_Even; //carEvent.Exceed_Speed_Even += Speed_Limit_Even2; carEvent.AddSpeed(); carEvent.AddSpeed(); carEvent.AddSpeed(); Console.ReadLine(); } public void AddSpeed() { int v = speed + 10; if (v > Warn_Speed && Exceed_Speed_Even!=null) { Exceed_Speed_Even(); } else { this.speed = v; } } // private static void Speed_Limit_Even() { Console.WriteLine("超速警告~~~"); } /*private static void Speed_Limit_Even2() { Console.WriteLine("超速警告0002~~~"); }*/ }}
线程 被定义为程序的执行路径。每个线程都定义了一个独特的控制流。如果您的应用程序涉及到复杂的和耗时的操作,那么设置不同的线程执行路径往往是有益的,每个线程执行特定的工作。
线程是轻量级进程。一个使用线程的常见实例是现代操作系统中并行编程的实现。使用线程节省了 CPU 周期的浪费,同时提高了应用程序的效率。
线程生命周期开始于 System.Threading.Thread 类的对象被创建时,结束于线程被终止或完成执行时。
下面列出了线程生命周期中的各种状态:
下面的示例演示简单的线程处理功能。
using System;using System.Threading;public class ThreadExample { public static void ThreadProc() { for (int i = 0; i < 10; i++) { Console.WriteLine("ThreadProc: {0}", i); Thread.Sleep(0); } } public static void Main() { Console.WriteLine("Main thread: Start a second thread."); Thread t = new Thread(new ThreadStart(ThreadProc)); t.Start(); //Thread.Sleep(0); for (int i = 0; i < 4; i++) { Console.WriteLine("i="+i); } //在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻止调用线程,直到由该实例表示的线程终止。 t.Join(); //终止线程 //t.Abort(); Console.WriteLine("程序已执行完毕"); Console.ReadLine(); }}
| ApartmentState | 已过时。 获取或设置此线程的单元状态。 |
|---|---|
| CurrentContext | 获取线程正在其中执行的当前上下文。 |
| CurrentCulture | 获取或设置当前线程的区域性。 (每个线程都具有由属性表示的区域性 CurrentCulture 和 UI 区域性,由 CurrentUICulture 属性表示。 当前区域性支持诸如分析和格式化、字符串比较和排序等区分区域性的操作,还可控制线程使用的书写体系和日历。 当前 UI 区域性提供对资源文件中的资源进行区分区域性的检索。) |
| CurrentPrincipal | 获取或设置线程的当前负责人(对基于角色的安全性而言)。 |
| CurrentThread | 获取当前正在运行的线程。(注意这个是个静态方法) |
| CurrentUICulture | 获取或设置资源管理器使用的当前区域性以便在运行时查找区域性特定的资源。 |
| ExecutionContext | 获取 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。 |
| IsAlive | 获取指示当前线程的执行状态的值。 |
| IsBackground | 获取或设置一个值,该值指示某个线程是否为后台线程。 |
| IsThreadPoolThread | 获取指示线程是否属于托管线程池的值。 |
| ManagedThreadId | 获取当前托管线程的唯一标识符。 |
| Name | 获取或设置线程的名称。 |
| Priority | 获取或设置指示线程的调度优先级的值。 |
| ThreadState | 获取一个值,该值包含当前线程的状态。 |
| Abort() | 在调用此方法的线程上引发 ThreadAbortException,以开始终止此线程的过程。 调用此方法通常会终止线程。 |
|---|---|
| Abort(Object) | 引发在其上调用的线程中的 ThreadAbortException 以开始处理终止线程,同时提供有关线程终止的异常信息。 调用此方法通常会终止线程。 |
| AllocateDataSlot() | 在所有线程上分配未命名的数据槽。 为了获得更好的性能,请改用以 ThreadStaticAttribute 特性标记的字段。 |
| AllocateNamedDataSlot(String) | 在所有线程上分配已命名的数据槽。 为了获得更好的性能,请改用以 ThreadStaticAttribute 特性标记的字段。 |
| BeginCriticalRegion() | 通知宿主执行将要进入一个代码区域,在该代码区域内线程中止或未经处理异常的影响可能会危害应用程序域中的其他任务。 |
| BeginThreadAffinity() | 通知主机托管代码将要执行依赖于当前物理操作系统线程的标识的指令。 |
| DisableComObjectEagerCleanup() | 对于当前线程关闭运行时可调用包装 (RCW) 的自动清理。 |
| EndCriticalRegion() | 通知主机执行将要进入一个代码区域,在该代码区域内线程中止或未经处理异常的影响限于当前任务。 |
| EndThreadAffinity() | 通知主机托管代码已执行完依赖于当前物理操作系统线程的标识的指令。 |
| Equals(Object) | 确定指定对象是否等于当前对象。 (继承自 Object ) |
| Finalize() | 确保垃圾回收器回收 Thread 对象时释放资源并执行其他清理操作。 |
| FreeNamedDataSlot(String) | 为进程中的所有线程消除名称与槽之间的关联。 为了获得更好的性能,请改用以 ThreadStaticAttribute 特性标记的字段。 |
| GetApartmentState() | 返回表示单元状态的 ApartmentState 值。 |
| GetCompressedStack() | 已过时。 返回 CompressedStack 对象,此对象可用于获取当前线程的堆栈。 |
| GetData(LocalDataStoreSlot) | 在当前线程的当前域中从当前线程上指定的槽中检索值。 为了获得更好的性能,请改用以 ThreadStaticAttribute 特性标记的字段。 |
| GetDomain() | 返回当前线程正在其中运行的当前域。 |
| GetDomainID() | 返回唯一的应用程序域标识符。 |
| GetHashCode() | 返回当前线程的哈希代码。 |
| GetNamedDataSlot(String) | 查找命名的数据槽。 为了获得更好的性能,请改用以 ThreadStaticAttribute 特性标记的字段。 |
| GetType() | 获取当前实例的 Type。 (继承自 Object ) |
| Interrupt() | 中断处于 WaitSleepJoin 线程状态的线程。 |
| Join() | 在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻止调用线程,直到由该实例表示的线程终止。 |
| Join(Int32) | 在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻止调用线程,直到由该实例表示的线程终止或经过了指定时间为止。 |
| Join(TimeSpan) | 在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻止调用线程,直到由该实例表示的线程终止或经过了指定时间为止。 |
| MemberwiseClone() | 创建当前 Object 的浅表副本。 (继承自 Object ) |
| MemoryBarrier() | 按如下方式同步内存访问:执行当前线程的处理器在对指令重新排序时,不能采用先执行 MemoryBarrier() 调用之后的内存存取,再执行 MemoryBarrier() 调用之前的内存存取的方式。 |
| ResetAbort() | 取消当前线程所请求的 Abort(Object)。 |
| Resume() | 已过时。 继续已挂起的线程。 |
| SetApartmentState(ApartmentState) | 在线程启动前设置其单元状态。 |
| SetCompressedStack(CompressedStack) | 已过时。 将捕获的 CompressedStack 应用到当前线程。 |
| SetData(LocalDataStoreSlot, Object) | 在当前正在运行的线程上为此线程的当前域在指定槽中设置数据。 为了提高性能,请改用用 ThreadStaticAttribute 属性标记的字段。 |
| Sleep(Int32) | 将当前线程挂起指定的毫秒数。 |
| Sleep(TimeSpan) | 将当前线程挂起指定的时间。 |
| SpinWait(Int32) | 导致线程等待由 iterations 参数定义的时间量。 |
| Start() | 导致操作系统将当前实例的状态更改为 Running。 |
| Start(Object) | 导致操作系统将当前实例的状态更改为 Running,并选择提供包含线程执行的方法要使用的数据的对象。 |
| Suspend() | 已过时。 挂起线程,或者如果线程已挂起,则不起作用。 |
| ToString() | 返回表示当前对象的字符串。 (继承自 Object ) |
| TrySetApartmentState(ApartmentState) | 在线程启动前设置其单元状态。 |
| VolatileRead(Byte) | 读取字段值。 无论处理器的数目或处理器缓存的状态如何,该值都是由计算机的任何处理器写入的最新值。 |
| VolatileRead(Double) | 读取字段值。 无论处理器的数目或处理器缓存的状态如何,该值都是由计算机的任何处理器写入的最新值。 |
| VolatileRead(Int16) | 读取字段值。 无论处理器的数目或处理器缓存的状态如何,该值都是由计算机的任何处理器写入的最新值。 |
| VolatileRead(Int32) | 读取字段值。 无论处理器的数目或处理器缓存的状态如何,该值都是由计算机的任何处理器写入的最新值。 |
| VolatileRead(Int64) | 读取字段值。 无论处理器的数目或处理器缓存的状态如何,该值都是由计算机的任何处理器写入的最新值。 |
| VolatileRead(IntPtr) | 读取字段值。 无论处理器的数目或处理器缓存的状态如何,该值都是由计算机的任何处理器写入的最新值。 |
| VolatileRead(Object) | 读取字段值。 无论处理器的数目或处理器缓存的状态如何,该值都是由计算机的任何处理器写入的最新值。 |
| VolatileRead(SByte) | 读取字段值。 无论处理器的数目或处理器缓存的状态如何,该值都是由计算机的任何处理器写入的最新值。 |
| VolatileRead(Single) | 读取字段值。 无论处理器的数目或处理器缓存的状态如何,该值都是由计算机的任何处理器写入的最新值。 |
| VolatileRead(UInt16) | 读取字段值。 无论处理器的数目或处理器缓存的状态如何,该值都是由计算机的任何处理器写入的最新值。 |
| VolatileRead(UInt32) | 读取字段值。 无论处理器的数目或处理器缓存的状态如何,该值都是由计算机的任何处理器写入的最新值。 |
| VolatileRead(UInt64) | 读取字段值。 无论处理器的数目或处理器缓存的状态如何,该值都是由计算机的任何处理器写入的最新值。 |
| VolatileRead(UIntPtr) | 读取字段值。 无论处理器的数目或处理器缓存的状态如何,该值都是由计算机的任何处理器写入的最新值。 |
| VolatileWrite(Byte, Byte) | 立即向字段写入一个值,以使该值对计算机中的所有处理器都可见。 |
| VolatileWrite(Double, Double) | 立即向字段写入一个值,以使该值对计算机中的所有处理器都可见。 |
| VolatileWrite(Int16, Int16) | 立即向字段写入一个值,以使该值对计算机中的所有处理器都可见。 |
| VolatileWrite(Int32, Int32) | 立即向字段写入一个值,以使该值对计算机中的所有处理器都可见。 |
| VolatileWrite(Int64, Int64) | 立即向字段写入一个值,以使该值对计算机中的所有处理器都可见。 |
| VolatileWrite(IntPtr, IntPtr) | 立即向字段写入一个值,以使该值对计算机中的所有处理器都可见。 |
| VolatileWrite(Object, Object) | 立即向字段写入一个值,以使该值对计算机中的所有处理器都可见。 |
| VolatileWrite(SByte, SByte) | 立即向字段写入一个值,以使该值对计算机中的所有处理器都可见。 |
| VolatileWrite(Single, Single) | 立即向字段写入一个值,以使该值对计算机中的所有处理器都可见。 |
| VolatileWrite(UInt16, UInt16) | 立即向字段写入一个值,以使该值对计算机中的所有处理器都可见。 |
| VolatileWrite(UInt32, UInt32) | 立即向字段写入一个值,以使该值对计算机中的所有处理器都可见。 |
| VolatileWrite(UInt64, UInt64) | 立即向字段写入一个值,以使该值对计算机中的所有处理器都可见。 |
| VolatileWrite(UIntPtr, UIntPtr) | 立即向字段写入一个值,以使该值对计算机中的所有处理器都可见。 |
| Yield() | 导致调用线程执行准备好在当前处理器上运行的另一个线程。 由操作系统选择要执行的线程。 |


可能文章排版存在问题,这边有生成pdf版本,有需要可以私聊。
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主
@作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors 1、什么是behaviors 2、behaviors的工作方式 3、创建behavior 4、导入并使用behavior 5、behavior中所有可用的节点 6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors 1、什么是behaviorsbehaviors是小程序中,用于实现
遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg
1.1.1 YARN的介绍 为克服Hadoop1.0中HDFS和MapReduce存在的各种问题⽽提出的,针对Hadoop1.0中的MapReduce在扩展性和多框架⽀持⽅⾯的不⾜,提出了全新的资源管理框架YARN. ApacheYARN(YetanotherResourceNegotiator的缩写)是Hadoop集群的资源管理系统,负责为计算程序提供服务器计算资源,相当于⼀个分布式的操作系统平台,⽽MapReduce等计算程序则相当于运⾏于操作系统之上的应⽤程序。 YARN被引⼊Hadoop2,最初是为了改善MapReduce的实现,但是因为具有⾜够的通⽤性,同样可以⽀持其他的分布式计算模