C#语法速览

C#是.net Franmework下的一门编程语言,语法与c类似。

命令行编译:csc

需要配置环境变量path:C:\Windows\Microsoft.NET\Framework64\v4.0.30319

VScode编写

相关快捷键:ctrl+`,打开终端(命令行)

  1. 打开终端
  2. 键入dotnet new console.
  3. 运行dotnet run

程序结构

一个C#程序主要包括主要包括以下部分:

用法:

参见:https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/compiler-options/command-line-building-with-csc-exe

基本语法

注释

多行注释以/* */开头结尾,单行注释以//开头。

/* This program demonstrates
The basic syntax of C# programing Language */
// end.

数据类型

常用的有

类型 默认值
bool False
byte o
char(unicode字符) ‘\0’
decimal(128位) 0.0M
double 0.0D
float 0.0F
int 0
long 0L
short(16位) 0
uint(无符号) 0

d/m/f/l大小写均可

注意: c#中,bool不能转换为int。

注:以下的type(T)指以上任意一种类型。

查看大小:sizeof(type) retVal:byte(s)

一个值类型转换为对象类型,称为装箱;一个对象类型转换为值类型,则被称为拆箱。

int val=8;
object obj=val;
int nval=(int)obj;
//常用方法
Replace,ToUpper,ToLower,Trim,Split,IndexOf
//属性:Length
public static string Format( string format, Object arg0 ) 
//前缀@表示不转义。

类型转换

允许变量在定义时初始化。

常量

定义: const type var=value;

运算符与表达式

流程

//判断语句
textexpr ? expr1:expr2;
if(textexpr1)
    expr1;
else if(textexpr2)
    expr2;
else
    expr3;
switch(expression)
{
    case constant-expr:
        expr;
        break;
    default:
        exprn;
        break;
}
//循环语句
while(condition)
    expr;
    break;
    continue;
for(init;condition;increment)
    expr;//在init声明的对象作用于整个块;
foreach(type element in array)
    expr;
//goto语句
goto check;
check:
x++;

数组

//声明数组
type[] arrayName;
//初始化数组
double[] balance=new double[10];//全部初始化为默认值
double[] balance={23.0,423.3,25.3};//声明的同时赋值
int[] marks=new int[5]{99,98,92,96,95};//与下式等价
int[] marks=new int[]{99,98,92,96,95};
int[] score=marks;//指向相同的地址。
string[,] names;
int [,] a = new int [3,4] {
 {0, 1, 2, 3} ,   /*  初始化索引号为 0 的行 */
 {4, 5, 6, 7} ,   /*  初始化索引号为 1 的行 */
 {8, 9, 10, 11}   /*  初始化索引号为 2 的行 */
};
//Array类的方法
Array.Reverse(marks)
Array.Sort(marks)

结构

结构的成员默认是公有的。

struct Books
{
   public string title;
   public string author;
   public string subject;
   public int book_id;
}; 

枚举

//枚举列表中的每个符号代表一个整数值,一个比它前面的符号大的整数值。
//默认情况下,第一个枚举符号的值是 0
enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };

文件

FileStream F = new FileStream("sample.txt", FileMode.Open, FileAccess.Read, FileShare.Read);

文件属性操作 File类与FileInfo都能实现。静态方法与实例化方法的区别

//use File class
Console.WriteLine(File.GetAttributes(filePath));
File.SetAttributes(filePath,FileAttributes.Hidden | FileAttributes.ReadOnly);
Console.WriteLine(File.GetAttributes(filePath));

//user FilInfo class
FileInfo fi = new FileInfo(filePath);
Console.WriteLine(fi.Attributes.ToString());
fi.Attributes = FileAttributes.Hidden | FileAttributes.ReadOnly; //隐藏与只读
Console.WriteLine(fi.Attributes.ToString());

//只读与系统属性,删除时会提示拒绝访问
fi.Attributes = FileAttributes.Archive;
Console.WriteLine(fi.Attributes.ToString());

函数

有四类参数,值参数,引用参数,输出参数,参数数组。

using System;
class Example
{

    static void Swap(ref int x, ref int y) 
    {
        int temp = x;
        x = y;
        y = temp;
    }
    public static void SwapExample() 
    {
        int i = 1, j = 2;
        Swap(ref i, ref j);
        Console.WriteLine($"{i} {j}");    // Outputs "2 1"
    }
    static void Divide(int x, int y, out int result, out int remainder) 
    {
        result = x / y;
        remainder = x % y;
    }
    public static void OutUsage() 
    {
        Divide(10, 3, out int res, out int rem);
        Console.WriteLine("{0} {1}", res, rem);	// Outputs "3 1"
    }   
}
public class Console
{
    public static void Write(string fmt, params object[] args) { }
    public static void WriteLine(string fmt, params object[] args) { }
    // ...
}
Console.WriteLine("x={0} y={1} z={2}", x, y, z);
string s = "x={0} y={1} z={2}";//与下式等价
object[] args = new object[3];
args[0] = x;
args[1] = y;
args[2] = z;
Console.WriteLine(s, args);

封装 类

class Program
    {
        static bool done=false;
        static readonly object locker = new object();
        static void Main(string[] args)
        {
            double[] balance = { 23.0, 423.3, 25.3 };//与下式等
            double b;
            b = 1l;
            string s=null;
            Console.WriteLine(s);
            Console.ReadKey();
        }
    }
    public class Point
    {
        public int x, y;
        public Point(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
    }
    public class Point3D : Point
    {
        public int z;
        public Point3D(int x, int y, int z) :
            base(x, y)//方法也可以继承
        {
            this.z = z;
        }
    }

接口

接口口定义了所有类继承接口时应遵循的语法合同。接口定义了语法合同 “是什么” 部分,派生类定义了语法合同 “怎么做” 部分。

接口定义了可由类和结构实现的协定。 接口可以包含方法、属性、事件和索引器。 接口不提供所定义的成员的实现代码,仅指定必须由实现接口的类或结构提供的成员。

接口使得实现接口的类或结构在形式上保持一致。

虚类和抽象类

如果实例方法声明中有 virtual 修饰符,可以将实例方法称为“虚方法”。 如果没有 virtual 修饰符,可以将实例方法称为“非虚方法”。

调用虚方法时,为其调用方法的实例的运行时类型决定了要调用的实际方法实现代码。 调用非虚方法时,实例的编译时类型是决定性因素。

可以在派生类中重写虚方法。 如果实例方法声明中有 override 修饰符,那么实例方法可以重写签名相同的继承虚方法。 但如果虚方法声明中引入新方法,重写方法声明通过提供相应方法的新实现代码,专门针对现有的继承虚方法。

抽象方法是没有实现代码的虚方法。 抽象方法使用 abstract 修饰符进行声明,只能在同样声明了 abstract 的类中使用。 必须在所有非抽象派生类中重写抽象方法。

C# 允许您使用关键字 abstract 创建抽象类,用于提供接口的部分类的实现。当一个派生类继承自该抽象类时,实现即完成。抽象类包含抽象方法,抽象方法可被派生类实现。派生类具有更专业的功能。

请注意,下面是有关抽象类的一些规则:

区别与联系:

  1. 虚方法要实现。虚方法必须有实现部分,并为派生类提供了重写该方法的选项。抽象方法没有提供实现部分,抽象方法是一种强制派生类重写的方法,否则派生类将不能被实例化。
//抽象方法
public abstract class Animal
{
    public abstract void Sleep();
    public abstract void Eat();
}

//虚方法
public class Animal
{
    public virtual void Sleep(){}
    public virtual void Eat(){}
}
  1. 有抽象方法的类必须声明为抽象类。抽象方法只能在抽象类中声明, 抽象方法必须在派生类中重写(override)。虚方法不是也不必要重写。其实如果类包含抽象方法,那么该类也是抽象的,也必须声明为抽象的。

  2. 两者重写都用override关键字。

高级特性

lambda表达式

lambda表达式是一个简短的函数

(input-parameters)=>expression//(当参数为一个时,括号可以省略)
(x,y)=>x==y
(int x, string s)=> s.Length>x//如果无法推断类型

泛型

运算符重载

public static Box operator+ (Box b, Box c)
{
   Box box = new Box();
   box.length = b.length + c.length;
   box.breadth = b.breadth + c.breadth;
   box.height = b.height + c.height;
   return box;
}

异常

try
{
   // 引起异常的语句
}
catch( ExceptionName e1 )
{
   // 错误处理代码
}
catch( ExceptionName e2 )
{
   // 错误处理代码
}
catch( ExceptionName eN )
{
   // 错误处理代码
}
finally
{
   // 要执行的语句
}