前言:最近在维护一个获取http接口的数据然后填充到Excel的工具,于是接触到了C#,总体感觉下来,C#关键字多,语法多,功能强大,LINQ感觉实现了一个C#版本的SQL。

基本结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
using System;  /* 引入System命名空间 */
namespace HelloWorldApplication /* 命名空间声明 */
{
   class HelloWorld /* 类 */
   {
      static void Main(string[] args) /* Main方法*/
      {
         Console.WriteLine("Hello World");
         Console.ReadKey();
      }
   }
}

基本语法

  • 语句以;结尾
  • 大小写敏感
  • 程序入口为Main方法

项目构建

  • 创建
1
dotnet new console -o myApp
  • 运行
1
2
cd myApp
dotnet run

类型和变量

值类型
  • 简单类型
    • 有符号的整型: sbyte、short、int、long
    • 无符号整型: byte、ushort、unit、ulong
    • 字符: char
    • 小数: float、double、decimal
    • 布尔: bool
  • 枚举类型: enum E{…}
  • 结构类型: strcut S {…}
  • null
引用类型
    • object 所有类型的基类
    • string
    • Class C {…} 自定义类
  • 接口类型 interface I {…}
  • 数组类型 如int[]、 int[,]
  • 委托类型 delegate int D(…)
引用类型

语句

  • if
1
2
3
4
if (...)
{}
else
{}
  • switch
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
switch (n)
{
    case 0:
        ...
        break;
    case 1:
        ...
        break;
    defaut:
        ...
}
  • while
1
2
while (i < 100)
{}
  • do-while
1
2
3
4
do
{
...
} while (i > 100);
  • for
1
2
3
4
for (int i = 0; i < 100; i++;)
{
    ...
}
  • foreach
1
2
3
4
5
int[] l = {1, 2, 3};
foreach (int i in l)
{
    Console.WriteLine(i);
}
  • goto
  • yield
  • checked/unchecked
  • throw
  • try
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
try
{
...
}
catch (Exception e)
{
}
finally
{
}
  • lock
  • using

类和对象

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

/* 申明 */
public class Point
{
    public int x, y;
    public Point(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}


/* 实例化 */

Point p1 = new Point(10, 20);

/* 继承 */

public class Point3D: Point
{
    public int z;
    public Point3D(int x, int y, int z):
        base(x, y)
    {
        this.z = z;
    }
    
}

成员

  • 分为静态成员和实例成员,静态属于类,实例成员属于类实例
  • 成员类型
    • 常量
    • 字段
    • 方法
    • 属性
    • 索引器
    • 事件
    • 运算符
    • 构造函数
    • 终结器
    • 类型

可访问性

  • public 访问不受限制
  • protectd 访问仅限于此类或派生类
  • internal 仅限数于当程序集(exe、ddl等)
  • protected internal 此类或派生类或当前程序集中的类
  • private 仅限于此类
  • private protected 此类或者当前程序集的派生类

类型参数(泛型)

1
2
3
4
5
6
7
8
/* 类名后用尖括号申明类型参数列表 */
public class Pair<TFirst, TSecond>
{
    public TFirst First;
    public TSecond Second;
}

Pair<int, string> pair = new Pair<int, string> {First = 1, Second = "two"}

字段

静态字段无论创建多少个类实例,都只有一个副本

1
2
3
4
5
6
public class Color
{
    public static readonly Color Black = new Color(0, 0, 0);
    public static readonly Color White = new Color(255, 255, 255);
    private byte r, g, b;
}

方法

参数
  • 值参数: 传值, 可以指定默认值
  • 引用参数: 传引用 使用ref修饰
1
2
3
4
5
6
7
8
9
static void Swap(ret int x, ret int y)
{
    int temp = x;
    x = y;
    y = temp;
}

int i = 2, y = 10;
Swap(ref i, ref y);
  • 输出参数: 传引用, 使用out修饰
1
2
3
4
5
6
7
static void Divide(int x, int y, out int result, out int remainder)
{
    result = x / y;
    remainer = x % y;
}
Diiden(10, 3, out int res, out int rem);
Console.WriteLine("{0} {1}", res, rem);
  • 参数数组 使用params修饰,只能位于最后,只能是一维数组
1
2
3
4
5
6
public class Console
{
    public static void Write(string fmt, params object[] args) { }
    public static void WriteLine(string fmt, params object[] args) { }
    // ...
}
方法主体和局部变量
静态和实例方法

使用static声明的方法是静态方法,静态方法只能访问静态成员 不使用static声明的方法是实例方法,实例方法可是访问静态和实例成员,可以使用this显示访问

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Entity
{
    static int nextSerialNo;
    int serialNo;
    public Entity() 
    {
        serialNo = nextSerialNo++;
    }
    public int GetSerialNo() 
    {
        return serialNo;
    }
    public static int GetNextSerialNo() 
    {
        return nextSerialNo;
    }
    public static void SetNextSerialNo(int value) 
    {
        nextSerialNo = value;
    }
}
虚方法、重载方法和抽象方法
  • 虚方法 virtual修饰
  • 抽象方法 abstract
  • 重新方法 override
方法重载
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using System;
class OverloadingExample
{
    static void F() 
    {
        Console.WriteLine("F()");
    }
    static void F(object x) 
    {
        Console.WriteLine("F(object)");
    }
    static void F(int x) 
    {
        Console.WriteLine("F(int)");
    }
    static void F(double x) 
    {
        Console.WriteLine("F(double)");
    }
    static void F<T>(T x) 
    {
        Console.WriteLine("F<T>(T)");
    }
    static void F(double x, double y) 
    {
        Console.WriteLine("F(double, double)");
    }
    public static void UsageExample()
    {
        F();            // Invokes F()
        F(1);           // Invokes F(int)
        F(1.0);         // Invokes F(double)
        F("abc");       // Invokes F<string>(string)
        F((double)1);   // Invokes F(double)
        F((object)1);   // Invokes F(object)
        F<int>(1);      // Invokes F<int>(int)
        F(1, 1);        // Invokes F(double, double)
    }
}

其他

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
public class MyList<T>
{
    // Constant
    const int defaultCapacity = 4;

    // Fields
    T[] items;
    int count;

    // Constructor
    public MyList(int capacity = defaultCapacity) 
    {
        items = new T[capacity];
    }

    // Properties
    public int Count => count; 

    public int Capacity 
    {
        get { return items.Length; }
        set 
        {
            if (value < count) value = count;
            if (value != items.Length) 
            {
                T[] newItems = new T[value];
                Array.Copy(items, 0, newItems, 0, count);
                items = newItems;
            }
        }
    }

    // Indexer
    public T this[int index] 
    {
        get 
        {
            return items[index];
        }
        set 
        {
            items[index] = value;
            OnChanged();
        }
    }
    
    // Methods
    public void Add(T item) 
    {
        if (count == Capacity) Capacity = count * 2;
        items[count] = item;
        count++;
        OnChanged();
    }
    protected virtual void OnChanged() =>
        Changed?.Invoke(this, EventArgs.Empty);

    public override bool Equals(object other) =>
        Equals(this, other as MyList<T>);

    static bool Equals(MyList<T> a, MyList<T> b) 
    {
        if (Object.ReferenceEquals(a, null)) return Object.ReferenceEquals(b, null);
        if (Object.ReferenceEquals(b, null) || a.count != b.count)
            return false;
        for (int i = 0; i < a.count; i++) 
        {
            if (!object.Equals(a.items[i], b.items[i])) 
            {
                return false;
            }
        }
    return true;
    }

    // Event
    public event EventHandler Changed;

    // Operators
    public static bool operator ==(MyList<T> a, MyList<T> b) => 
        Equals(a, b);

    public static bool operator !=(MyList<T> a, MyList<T> b) => 
        !Equals(a, b);
}
构造函数 : 和类名相同,无返回值
属性: 不指明存储位置,set和get设置读写属性
1
2
3
4
MyList<string> names = new MyList<string>();
names.Capacity = 100;   // Invokes set accessor
int i = names.Count;    // Invokes get accessor
int j = names.Capacity; // Invokes get accessor
索引器
事件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class EventExample
{
    static int changeCount;
    static void ListChanged(object sender, EventArgs e) 
    {
        changeCount++;
    }
    public static void Usage() 
    {
        MyList<string> names = new MyList<string>();
        names.Changed += new EventHandler(ListChanged);
        names.Add("Liz");
        names.Add("Martha");
        names.Add("Beth");
        Console.WriteLine(changeCount);		// Outputs "3"
    }
}

数组

1
int a = new int[]{1,2,3}
  • 数组中的元素均为同一种类型
  • new运算指定了实例的长度,此长度不可变
  • 默认值为0或null
  • L.length访问长度

接口

定义了可有类或结构实现的成员,可以多重继承,类也可以实现多个接口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
interface IControl
{
    void Paint();
}

interface IDataBound
{
    void BInd(BInd b);
}
public class EditBox: IContril, IDataBound
{
    public void Paint() {}
    public void Bind(Bind b) {}
}

类可以隐式转换成相应的接口类型

1
2
EditBox editBox = new EdixBox();
IControl control = eidBox;

委托

实现将方法作为参数传递

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using System;
delegate double Function(double x);
class Multiplier
{
    double factor;
    public Multiplier(double factor) 
    {
        this.factor = factor;
    }
    public double Multiply(double x) 
    {
        return x * factor;
    }
}
class DelegateExample
{
    static double Square(double x) 
    {
        return x * x;
    }
    static double[] Apply(double[] a, Function f) 
    {
        double[] result = new double[a.Length];
        for (int i = 0; i < a.Length; i++) result[i] = f(a[i]);
        return result;
    }
    static void Main() 
    {
        double[] a = {0.0, 0.5, 1.0};
        double[] squares = Apply(a, Square);
        double[] sines = Apply(a, Math.Sin);
        Multiplier m = new Multiplier(2.0);
        double[] doubles =  Apply(a, m.Multiply);
    }
}

可以使用匿名函数创建委托

1
double[] doubles = Apply(a, (double x) => x * 2.0);

参考