注:笔者有 C++ Java Python 等语言的基础,主要目的是混个分,看看就行别太认真。

大概的语法很像 Java ,存在 Java 基础学习 C# 只需要半天。

文件后缀为 .cs

  • 有统一类型系统
  • 可以为 null 的类型可防范不引用已分配对象的变量
  • 这句话我也没看明白

    .NET体系

    C# 是编程语言, .NET 是框架

    C# 程序在 .NET 上运行,前者是后者的一部分,不做赘述

    C# C++ Visual Basic Jscript COBOL 等都可以在上面运行

    C# 的 helloworld
    // 调用System命名空间
    using System;
    // 命名空间声明,包含了类
    namespace HelloWorldApplication
        // 类声明
        class HelloWorld
            // main 方法,程序的入口
            static void Main(string[] args)
                // 单行注释
                /// 三斜杠注释,符合个人习惯就行
                /* 多行注释
                   我的第一个 C# 程序
                // 打印 helloworld
                Console.WriteLine("Hello World");
                // pause 暂停,等待继续
                Console.ReadKey();
    
  • 区分大小写
  • 字母、下划线和 @ 开头
  • 后面可以是字母、下划线、@ 和数字
  • 不能与类名相同
  • 不能是关键字,除非前缀有 @
  • 我也没深究 @ 有什么含义,注解吗难不成

    值类型引用类型和指针类型

  • 有符号整型:sbyteshortintlong
  • 无符号整型:byteushortuintulong
  • Unicode 字符:char,表示 UTF-16 代码单元
  • IEEE 二进制浮点:floatdouble
  • 高精度十进制浮点数:decimal
  • 布尔值:bool,表示布尔值(truefalse
  • enum E {...} 格式的用户定义类型。 enum 类型是一种包含已命名常量的独特类型。 每个 enum 类型都有一个基础类型(必须是八种整型类型之一)。 enum 类型的值集与基础类型的值集相同。
  • 格式为 struct S {...} 的用户定义类型
  • 可以为 null 的值类型
  • 值为 null 的其他所有值类型的扩展
  • 元组值类型
  • 格式为 (T1, T2, ...) 的用户定义类型
  • 其他所有类型的最终基类:object
  • Unicode 字符串:string,表示 UTF-16 代码单元序列
  • 格式为 class C {...} 的用户定义类型
  • 格式为 interface I {...} 的用户定义类型
  • 一维、多维和交错。 例如:int[]int[,]int[][]
  • 格式为 delegate int D(...) 的用户定义类型
  • 类型声明:六种

    类类型、结构类型、接口类型、枚举类型、委托类型和元组值类型。

  • Class 类
  • Struct 结构
  • Interface 接口
  • Delegate 委托
  • 类似于函数的指针

    以上类型全部支持泛型,可用其他类型参数化

    动态(Dynamic)类型

  • 与对象类型相似
  • 对象类型在编译时检查
  • 动态类型在运行时检查类型
  • 类似于脚本语言的 var

    字符串类型

    虽然 C# 区分大小写,但是 string 关键字是 String 的别名,正常使用时可以看作是等价的。

    C# 中,string 的使用优先级似乎比 String 要高,我也不知道为啥,不太习惯。

    字符串(String)类型的值可以通过两种形式进行分配:引号和 @引号。

    逐字字符串:可以将转义字符(\)当作普通字符,相当于(\\)

    @ 之后就不用转义了吧,方便cv,看起来也顺眼一点

    string str = @"C:\Windows";
    string str = "C:\\Windows";
    

    @ 字符串中可以任意换行,换行符及缩进空格都计算在字符串长度之内。

    string str = @"<script type=""text/javascript"">
    </script>";
    

    与C和C++相同,万事不觉星号批(*p

    nullable 类型

    可空类型,在基础值类型的范围,加上 null

    Nullable<Int32> // 可空的 Int32 类型;
    Nullable<bool> // true、false 和 null
    

    单问号?和双问号??

    大概解读:

  • 单问号赋予数据类型可以为 null
  • 双问号判断是否为 null,然后赋值。赋非空值。
  • 单问号:使数据类型可空

    ? 单问号用于对 intdoublebool 等无法直接赋值为 null 的数据类型进行 null 的赋值

    int? i = 3;
    Nullable<int> i = new Nullable<int>(3);
    
    int i;// 默认值:0
    int? ii;// 默认值:null
    
    双问号:合并运算符(??)

    ?? 双问号用于判断一个变量在为 null 的时候返回一个指定的值。

  • 若第一个为 null, 则返回第二个数值
  • 若第一个不为 null,则返回第一个数值
  • double? num1 = null;
    double? num2 = 3.14;
    double num3;
    num3 = num1 ?? 5.34; // num1 为空,返回5.34
    num3 = num2 ?? 5.34; // 非空,,返回3.14
    

    简单的输入与输出

    System 命名空间中的 Console 类提供了一个函数 ReadLine()

    int num;
    // 读取,接受,并转类型为32位int
    num = Convert.ToInt32(Console.ReadLine());
    
    Console.Write();
    /// cout<<"";
    /// System.out.print();
    /// print();
    Console.WriteLine();
    /// cout<<endl;
    /// System.out.println();
    

    函数与方法

    值传递和引用传递

    值传递,不影响原数据:

    public void swap(int x, int y){
        int temp;
        temp = x; /* 保存 x 的值 */
        x = y;    /* 把 y 赋值给 x */
        y = temp; /* 把 temp 赋值给 y */
    

    引用传递ref (Reference)关键字关联参考

    public void swap(ref int x, ref int y){
        int temp;
        temp = x; /* 保存 x 的值 */
        x = y;    /* 把 y 赋值给 x */
        y = temp; /* 把 temp 赋值给 y */
    

    访问修饰符

    publicprivateprotected

  • public 公开
  • private 私有,子类也无法访问
  • protected 保护,子类可以继承调用
  • protected internal:引用程序集内公开(package public?)
  • 默认是 internal

    Internal 内部

  • internal 只能在命名空间内(项目内)被访问到。
  • public 修饰的是可以在命名空间外(项目外)访问到的。
  • 任意类型一维数组和多维数组
  • 无需声明直接使用
  • int[] 一维数组
  • int[,] 二维数组
  • int[][] int 类型的一维数组或“交错”数组构成的一维数组
  • C# 数组细节

  • 交错数组,数组的数组
  • 传递数组给函数,传递指针
  • 参数数组,传参
  • Array 类。System命名空间中定义,数组的基类。
  • 数组的通解

    经典千篇一律

    data[] arrayName;
    
    初始化数组

    声明数组不会初始化。

    数组是引用类型,需要用 new 关键字创建实例。

    double[] balance = new double[10];
    

    存在隐式初始化,例如 int 数组默认值为 0

    单个元素赋值

    balance[0] = 4500.0;
    

    声明数组时赋值

    double[] balance = { 2340.0, 4523.69, 3421.0};
    

    复制数组,此时引用地址相同,指针地址相同。

    int[] marks = new int[] {xx,xxx};
    int[] score = marks;
    
    访问数组元素
  • 通过下标单个访问
  • foreach 遍历循环
  • 交错数组是数组的数组,可以包含多维数组

  • 交错数组的元素是数组
  • 各元素之前长度可以不同,可以是一维数组,也可以是二维数组。
  • 声明数组,具有3个元素,每个元素都是一个数组

    int[][] jaggedArray = new int[3][];
    

    对每个元素数组开始初始化

    jaggedArray[0] = new int[5];
    jaggedArray[1] = new int[4];
    jaggedArray[2] = new int[2];
    

    此时,每个元素都是一个一维数组,但是长度各不相同

    赋值初始化:

    jaggedArray[0] = new int[] { 1, 3, 5, 7, 9 };
    jaggedArray[1] = new int[] { 0, 2, 4, 6 };
    jaggedArray[2] = new int[] { 11, 22 };
    

    也可以在交错数组声明时初始化

    int[][] jaggedArray2 = new int[][]{
        new int[] { 1, 3, 5, 7, 9 },
        new int[] { 0, 2, 4, 6 },
        new int[] { 11, 22 }
    

    总结:数组的数组,与多维数组最大的不同是对每个一维/多维数组的长度没有要求。

    结构体(Struct)

    struct Books{
        public string title;
        public int book_id;
    

    结构体与类

    C# 中,二者默认访问权限均为 private

  • 前者是值类型,在栈上分配内存
  • 后者是引用类型,在堆上分配内存
  • 结构不能继承
  • 结构不能声明默认构造函数
  • 结构中不能赋予默认初始值
  • 静态构造函数:C# 的结构可以定义构造函数

  • 结构可带有方法、字段、索引、属性、运算符方法和事件。
  • 可以实现一个或多个接口
  • 使用 New 创建实例,会调用构造函数
  • 与类不同,结构可以不使用 New 即可实例化。
  • 此时(不使用 new),所有字段初始化之后,字段才被赋值,对象才被使用。
  • 再多的没研究

    基于VS的C#项目的结构

    解决方案:.sln 项目入口

    项目文件:.csproj

    命名空间和类:.cs

    Properties 文件夹:
        项目版本信息定义,编译方式定义等
    bin 文件夹:
        项目发布,生成文件夹
        Debug 文件夹:
            调试版本输出,含有断电调试信息等
        Release 文件夹:
            运行版本输出
    obj 文件夹:
        vs开发编译缓存
    

    注:Properties、bin、obj,这几个文件夹不需要程序员管理

    *.config 文件:
        Asp.net 配置文件
    appsettings.json 文件:
        .Net Core 配置文件定义
    

    文件管理器目录

    |-- Properties | |-- AssemblyInfo.cs 存储当前项目的程序集信息 | |--Program.cs 源代码文件

    本地目录结构:/xxx/source/repos/ConsoleApp1/

    |-- ConsoleApp1 项目文件夹
    |   |-- bin [编译]保存项目生成后的程序集,存在Debug 和 Release 两个版本。默认输出路径。
    |   |   |-- Debug
    |   |   |   |-- .exe 或 .dll
    |   |   |   |-- .pdb 记录断点、调试信息
    |   |   |   |-- .XML
    |   |   |-- Release
    |   |   |   |-- .exe 或 .dll
    |   |   |   |-- .pdb
    |   |-- obj [编译]保存每个模块的编译结果
    |   |-- Properties
    |   |   |-- AssemblyInfo.cs 存储当前项目的程序集信息
    |   |-- App.config 
    |   |-- ConsoleApp1.csproj 项目的配置文件
    |   |-- Program.cs 核心文件,源代码
    |-- ConsoleApp1.sln  解决方案文件,vs打开的入口
    

    一般一直或打包程序,只需要 Debug 文件即可。

    包含.exe文件、.dll文件、.ini文件、.xml文件、.pdb文件、.lib文件、.config.manifest文件、.png文件、.gif文件、.cur文件、自定义文件夹等。

    \bin\release\ 目录下只有一个 .exe.dll 文件,Release 模式下不包含调试信息,并对代码进行了优化。

    可执行文件:bin\Debug\

    ConsoleApp1.exe:
        可执行文件,双击可以直接运行。
    ConsoleApp1.exe.config:
        应用程序的配置文件,上面介绍的App.config文件的克隆。
    ConsoleApp1.pdb:
        .pdb(Program Database File,程序数据库文件),VS编译链接时生成的文件。
        DPB文件主要存储了 VS 调试程序时所需要的基本信息,主要包括源文件名、变量名、函数名、FPO(帧指针)、对应的行号等等。
        因为存储的是调试信息,所以一般情况下PDB文件是在Debug模式下才会生成。
    

    namespace 命名空间

    C#namespacepackage 有点像

    区别与联系:

  • 命名空间只是逻辑上的结构,允许物理位置与逻辑结构不一样
  • Java 中类文件的物理结构与逻辑结构必须一致
  • Javapackage 没有子包,package 之间互相并列,没有包含关系
  • C#namespace 允许有自己的 sub-namespace
  • Java 使用 import,而 C# 使用 using namespace
  • out 关键字

  • 类似 ref,使参数变为引用传递。
  • 区别是,out 在调用函数前强制要求初始化
  • 二者在编译时是一样的,所以无法因为关键字不一样重载
  • 作用:便于通过 out 返回多个值

    分类:
    后端
    标签: