参考资料:

https://github.com/derekbanas/C-Sharp-Course/tree/main

参考文档:

https://www.tutorialsteacher.com/csharp/csharp-version-history

01 - Data

  • 字符串转化成其他类型:

    1
    2
    3
    bool boolFromStr = bool.Parse("true");
    int intFromStr = int.Parse("123");
    double dblFromStr = double.Parse("3.1415");
  • 其他类型转化成字符串:

    1
    string str = dblFromStr.ToString();
  • 格式转换

    可以使用的参数有:货币表示、填充、精确到几位小数、逗号隔开

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    //货币 
    //Currency : ¥23.45
    Console.WriteLine("Currency : {0:c}", 23.455);
    //向前填充
    //Pad with 0s : 0023
    Console.WriteLine("Pad with 0s : {0:d4}", 23);
    //精确到三位小数
    //3 Decimals : 23.456
    Console.WriteLine("3 Decimals : {0:f3}", 23.45555);
    //逗号隔开
    //Commmas : 2,300.0000
    Console.WriteLine("Commmas : {0:n4} ", 2300);
    //逗号隔开
    //Commmas : 230,000,000
    Console.WriteLine("Commmas : {0:n0} ", 230000000);
  • 字符串操作

    字符串操作包括:取大小、是否包含、索引位置、删除、插入、替换、对比

    填充、全部大写、全部小写

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    string randString = "This is a string";
    Console.WriteLine("String Length : {0}", randString.Length);
    Console.WriteLine("String Contains is : {0}", randString.Contains("is"));
    Console.WriteLine("Index of is : {0}", randString.IndexOf("is"));
    Console.WriteLine("Remove String : {0}", randString.Remove(10, 6));
    Console.WriteLine("Insert String : {0}", randString.Insert(10, "short "));
    Console.WriteLine("Replace String : {0}", randString.Replace("string", "sentence"));
    Console.WriteLine("Compare A to B : {0}", String.Compare("A", "B", StringComparison.OrdinalIgnoreCase));

    Console.WriteLine("-------------------");

    Console.WriteLine("A = a : {0}", String.Equals("A", "a", StringComparison.OrdinalIgnoreCase));
    Console.WriteLine("Pad Left : {0}", randString.PadLeft(20, '.'));
    Console.WriteLine("Pad Right : {0}", randString.PadRight(20, '.'));
    // Trim whitespace
    Console.WriteLine("Trim : {0}", randString.Trim());
    Console.WriteLine("Uppercase : {0}", randString.ToUpper());
    Console.WriteLine("Lowercase : {0}", randString.ToLower());
    string newString = String.Format("{0} saw a {1} {2} in the {3}", "Paul", "rabbit", "eating", "field");
    Console.Write(newString + "\n");

    Console.WriteLine(@"Exactly what I type\n");

    结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    String Length : 16
    String Contains is : True
    Index of is : 2
    Remove String : This is a
    Insert String : This is a short string
    Replace String : This is a sentence
    Compare A to B : -1
    -------------------
    A = a : True
    Pad Left : ....This is a string
    Pad Right : This is a string....
    Trim : This is a string
    Uppercase : THIS IS A STRING
    Lowercase : this is a string
    Paul saw a rabbit eating in the field
    Exactly what I type\n
  • 数组操作

    支持多种类型:基础数据类型、未定义类型、多种数据类型

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    int[] favNums = new int[3]; 
    favNums[0] = 23;
    Console.WriteLine("favNum 0 : {0}", favNums[0]);
    string[] customers = { "Bob", "Sally", "Sue" };
    var employees = new[] { "Mike", "Paul", "Rick" };
    object[] randomArray = { "Paul", 45,1.234 };

    Console.WriteLine("randomArray 0 : {0}", randomArray[0].GetType());
    Console.WriteLine("Array Size : {0}", randomArray.Length);

    for (int j = 0; j < randomArray.Length; j++)
    {
    Console.WriteLine("Array : {0}: Value : {1}", j, randomArray[j]);
    }

    二维数组的操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    Console.WriteLine("---------------------------");

    string[,] custNames = new string[2, 2]{{ "Bob", "Sam"}, { "Sally", "Smith" }};
    Console.WriteLine("MD Value : {0}", custNames.GetValue(1,0));

    for (int j = 0; j < custNames.GetLength(0); j++)
    {
    for (int k = 0; k < custNames.GetLength(0); k++)
    {
    Console.WriteLine("{0} ",custNames[j, k]);
    }
    Console.WriteLine();
    }

    int[] randNums = { 3, 4, 1, 2 };
    PrintArray(randNums, "ForEach");

    数组方法

    包括排序、反转、索引、设置值、复制

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    Console.WriteLine("---------------------------");

    Array.Sort(randNums);
    Array.Reverse(randNums);
    Console.WriteLine("1 at index: {0}", Array.IndexOf(randNums, 1));
    randNums.SetValue(0, 1);
    int[] srcArray = { 1, 2, 3 };
    int[] desArray = new int[2];
    int startId = 0;
    int length = 2;
    Array.Copy(srcArray, startId, desArray, 0, length);
    PrintArray(desArray, "Copy");

    Array anotherArray = Array.CreateInstance(typeof(int), 10);
    srcArray.CopyTo(anotherArray, 5);

    foreach (int m in anotherArray)
    {
    Console.WriteLine("CopyTo : {0} ", m);
    }
  • C#中能用到的条件语句

    • if/else
    • 三元表达式
    • switch
    • Equals函数
  • 随机数的使用

    1
    2
    Random random = new Random();
    int[] rand = random.Next(1, 11);

    这段代码可以生成1~10之间的随机数

  • 时间

    这个例子中有两种类型:DateTimeTimeSpan,以下是他们的用例

    • DateTime
    1
    2
    3
    4
    5
    6
    7
    DateTime awesomeDate = new DateTime(1974, 12, 21);
    Console.WriteLine("Day of Week : {0}", awesomeDate.DayOfWeek);

    awesomeDate = awesomeDate.AddDays(4);
    awesomeDate = awesomeDate.AddMonths(1);
    awesomeDate = awesomeDate.AddYears(1);
    Console.WriteLine("New Date : {0}", awesomeDate.Date);
    • TimeSpan
    1
    2
    3
    4
    5
    TimeSpan lunchTime = new TimeSpan(12, 30, 0);

    lunchTime = lunchTime.Subtract(new TimeSpan(0, 15, 0));
    lunchTime = lunchTime.Add(new TimeSpan(1, 0, 0));
    Console.WriteLine("New Time : {0}", lunchTime.ToString());
  • 枚举

    可以指定类型,可以设置默认值,之后的值都是前面的加一

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    enum CarColor : byte
    {
    Orange = 1,
    Blue,
    Green,
    Red,
    Yellow
    }

    static void PaintCar(CarColor cc)
    {
    Console.WriteLine("The car was painted {0} with the code {1}",
    cc, (int)cc);
    }

02 - Exception Handeling

使用trycatch来处理可能发生异常的地方。

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
public class Program
{

static double Division_fn(double x, double y)
{
if(y == 0)
{
throw new System.DivideByZeroException();
}

return x / y;
}
static void Main(string[] args)
{
double num1 = 5;
double num2 = 0;

try
{
Console.WriteLine("5 / 0 = {0}", Division_fn(num1, num2));

}
catch (DivideByZeroException e)
{
Console.WriteLine(e.GetType().Name);
Console.WriteLine(e.Message);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}

}
}

03 - StringBuilder

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
StringBuilder sb = new StringBuilder("Random Text");

// Create a StringBuilder with a size of 256
StringBuilder sb2 = new StringBuilder("More Stuff that is very important", 256);

// Get max size
Console.WriteLine("Capacity : {0}", sb2.Capacity);

// Get length
Console.WriteLine("Length : {0}", sb2.Length);

// Add text to StringBuilder
sb2.AppendLine("\nMore important text");

// Define culture specific formating
CultureInfo enUS = CultureInfo.CreateSpecificCulture("en-US");

// Append a format string
string bestCust = "Bob Smith";
sb2.AppendFormat(enUS, "Best Customer : {0}", bestCust);

// Output StringBuilder
Console.WriteLine(sb2.ToString());

// Replace a string
sb2.Replace("text", "characters");
Console.WriteLine(sb2.ToString());

// Clear a string builder
sb2.Clear();

sb2.Append("Random Text");

// Are objects equal
Console.WriteLine(sb.Equals(sb2));

// Insert at an index
sb2.Insert(11, " that's Great");

Console.WriteLine("Insert : {0}", sb2.ToString());

// Remove number of characters starting at index
sb2.Remove(11, 7);

Console.WriteLine("Remove : {0}", sb2.ToString());

04 - Function

  • static:不用实例化,可以直接调用

  • ref:可以引用变量,传递参数的地址,使用ref前必须对变量赋值

  • out:out是传递返回的值,退出函数时所有out引用的变量都要赋值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public static void Swap(ref int num1, ref int num2)
    {
    int temp = num1;
    num1 = num2;
    num2 = temp;
    }
    static void Main(string[] args)
    {
    int num = 0;
    int num2 = 1;
    Console.WriteLine("Before Swap num1 : {0} num2 : {1}", num, num2);
    Swap(ref num, ref num2);
    Console.WriteLine("After Swap num1 : {0} num2 : {1}", num, num2);

    }
  • params:可以不限制地传入参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public static double GetSumMore(params double[] nums)
    {
    double sum = 0;
    foreach (double num in nums)
    {
    sum += num;
    }
    return sum;
    }

    static void Main(string[] args)
    {
    Console.WriteLine("1 + 2 + 3 + 4 + 5 + 6 = {0} ", GetSumMore(1, 2, 3, 4, 5, 6));

    }
  • 使用定义的参数就可以无需按需传入参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    static void PrintInfo(string name, int zipCode)
    {
    Console.WriteLine("{0} lives in the zip code {1}", name, zipCode);
    }


    static void Main(string[] args)
    {
    PrintInfo(zipCode: 15147,name: "Derek Banas");
    }
  • 函数重载

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    static double GetSum2(double x = 1, double y = 1)
    {
    return x + y;
    }

    static double GetSum2(string x = "1", string y = "1")
    {
    double dblX = Convert.ToDouble(x);
    double dblY = Convert.ToDouble(y);
    return dblX + dblY;
    }


    static void Main(string[] args)
    {
    Console.WriteLine("5.0 + 4.0 = {0}", GetSum2(5.0, 4.5));
    Console.WriteLine("5 + 4 = {0}", GetSum2(5, 4));
    Console.WriteLine("5 + 4 = {0}", GetSum2("5", "4"));
    }

05 - Class

  • internal:只能在程序集中可见

  • static:

    • 变量:所有实例共享一个变量
    • 函数:无需实例化即可使用的函数
  • 类的初始化方式

    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
    class Animal
    {
    private string name;
    private string sound;

    public const string SHELTER = "Derek's Home for Animals";

    public readonly int idNum;

    public void MakeSound()
    {
    Console.WriteLine("{0} says {1}",
    name, sound);
    }

    public Animal()
    : this("No Name", "No Sound") { }

    public Animal(string name)
    : this(name, "No Sound") { }

    public Animal(string name,
    string sound)
    {
    SetName(name);
    Sound = sound;

    NumOfAnimals = 1;

    Random rnd = new Random();
    idNum = rnd.Next(1, 2147483640);
    }

    public void SetName(string name)
    {
    if (!name.Any(char.IsDigit))
    {
    this.name = name;
    }
    else
    {
    this.name = "No Name";
    Console.WriteLine("Name can't contain numbers");
    }
    }

    public string GetName()
    {
    return name;
    }

    public string Sound
    {
    get { return sound; }
    set
    {
    if (value.Length > 10)
    {
    sound = "No Sound";
    Console.WriteLine("Sound is too long");
    }
    else
    {
    sound = value;
    }
    }
    }

    public string Owner { get; set; } = "No Owner";

    public static int numOfAnimals = 0;

    public static int NumOfAnimals
    {
    get { return numOfAnimals; }
    set { numOfAnimals += value; }
    }

    }

06 - Abstract Class

如果你想定义不被实例化的类。在这种情况下,可以使用抽象类。

基类:

1
2
3
4
5
6
7
8
9
10
11
abstract class Shape
{
public string Name { get; set; }

public virtual void GetInfo()
{
Console.WriteLine($"This is a {Name}");
}

public abstract double Area();
}

子类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Circle : Shape
{
public double Radius { get; set; }

public Circle(double radius)
{
Name = "Circle";
Radius = radius;
}

public override double Area()
{
return Math.PI * (Math.Pow(Radius, 2.0));
}

public override void GetInfo()
{
base.GetInfo();
Console.WriteLine($"It has a Radius of {Radius}");
}

}

基类的实例可以存储子类:

1
Shape[] shapes = {new Circle(5), new Rectangle(4,5)};

07 - Interface

接口类,其中的方法需要被实现

  • 以下是一个简单的例子:

    • 接口:

      1
      2
      3
      4
      5
      6
      7
      8
      interface IDrivable
      {
      int Wheels { get; set; }
      double Speed { get; set; }

      void Move();
      void Stop();
      }
    • 实现类:

      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
      class Vehicle : IDrivable
      {
      public string Brand { get; set; }

      public Vehicle(string brand = "No Brand",
      int wheels = 0,
      double speed = 0)
      {
      Brand = brand;
      Wheels = wheels;
      Speed = speed;
      }

      public double Speed { get; set; }

      public int Wheels { get; set; }

      public void Move()
      {
      Console.WriteLine($"The {Brand} Moves Forward at {Speed} MPH");
      }

      public void Stop()
      {
      Console.WriteLine($"The {Brand} Stops");
      Speed = 0;
      }
      }
  • 或者这样使用

    • 接口:

      1
      2
      3
      4
      5
      6
      7
      interface IElectronicDevice
      {
      void On();
      void Off();
      void VolumeUp();
      void VolumeDown();
      }
      1
      2
      3
      4
      5
      interface ICommand
      {
      void Execute();
      void Undo();
      }
    • 实现类:

      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
      class Television : IElectronicDevice
      {
      public int Volume { get; set; }

      public void Off()
      {
      Console.WriteLine("The TV is Off");
      }

      public void On()
      {
      Console.WriteLine("The TV is On");
      }

      public void VolumeDown()
      {
      if (Volume != 0) Volume--;
      Console.WriteLine($"The TV Volume is at {Volume}");
      }

      public void VolumeUp()
      {
      if (Volume != 100) Volume++;
      Console.WriteLine($"The TV Volume is at {Volume}");
      }
      }
      1
      2
      3
      4
      5
      6
      7
      class TVRemote
      {
      public static IElectronicDevice GetDevice()
      {
      return new Television();
      }
      }
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      class PowerButton : ICommand
      {
      IElectronicDevice device;

      public PowerButton(IElectronicDevice device)
      {
      this.device = device;
      }

      public void Execute()
      {
      device.On();
      }

      public void Undo()
      {
      device.Off();
      }
      }
    • 使用:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      static void Main(string[] args)
      {
      IElectronicDevice TV = TVRemote.GetDevice();
      PowerButton powBut = new PowerButton(TV);

      powBut.Execute();
      powBut.Undo();
      powBut.Execute();
      powBut.Undo();
      }

08 - Collections

需要引入以下依赖:

1
2
using System.Collections;
using System.Collections.Generic;

C#中有以下几种类型的集合

  • ArrayList
  • List
  • SortedList
  • Dictionary
  • Hashtable
  • Stack
  • Queue

ArrayList

可以存储多种数据结构的容器

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
#region ArrayList Code

ArrayList aList = new ArrayList();

aList.Add("Bob");
aList.Add(40);

Console.WriteLine("Count: {0}", aList.Count);
Console.WriteLine("Capacity: {0}", aList.Capacity);

ArrayList aList2 = new ArrayList();

aList2.AddRange(new object[] { "Mike", "Sally", "Egg" });
aList.AddRange(aList2);


aList2.Sort();
aList2.Reverse();

aList2.Insert(1, "Turkey");

ArrayList range = aList2.GetRange(0, 2);

Console.WriteLine("Turkey Index : {0}", aList2.IndexOf("Turkey", 0));

foreach (object o in range)
{
Console.WriteLine(o);
}

string[] myArray = (string[])aList2.ToArray(typeof(string));
string[] customers = { "Bob", "Sally", "Sue" };
ArrayList custArrayList = new ArrayList();
custArrayList.AddRange(customers);

#endregion

Dictionary

字典,存储一对键值,

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
#region Dictionary Code

Dictionary<string, string> superheroes = new Dictionary<string, string>();

superheroes.Add("Clark Kent", "Superman");
superheroes.Add("Bruce Wayne", "Batman");
superheroes.Add("Barry West", "Flash");
superheroes.Remove("Barry West");

Console.WriteLine("Count : {0}", superheroes.Count);
Console.WriteLine("Clark Kent : {0}", superheroes.ContainsKey("Clark Kent"));

superheroes.TryGetValue("Clark Kent", out string test);

Console.WriteLine($"Clark Kent : {test}");

foreach (KeyValuePair<string, string> item in superheroes)
{
Console.WriteLine("{0} : {1}", item.Key, item.Value);
}

superheroes.Clear();


#endregion

Queue

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
#region Queue Code

Queue queue = new Queue();

queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);

Console.WriteLine("1 in Queue : {0}", queue.Contains(1));

Console.WriteLine("Remove 1 : {0}", queue.Dequeue());

Console.WriteLine("Peek 1 : {0}", queue.Peek());

object[] numArray = queue.ToArray();

Console.WriteLine(string.Join(",", numArray));

foreach (object o in queue)
{
Console.WriteLine($"Queue : {o}");
}

queue.Clear();


#endregion

Stack

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#region Queue Code

Stack stack = new Stack();

stack.Push(1);
stack.Push(2);
stack.Push(3);

Console.WriteLine("Peek 1 : {0}", stack.Peek());

Console.WriteLine("Pop 1 : {0}", stack.Pop());

Console.WriteLine("Contain 1 : {0}", stack.Contains(1));

object[] numArray2 = stack.ToArray();

Console.WriteLine(string.Join(",", numArray2));

foreach (object o in stack)
{
Console.WriteLine($"Stack : {o}");
}
#endregion

09 - Generic

  • 类的泛型

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    internal class Animal
    {
    public string Name { get; set; }
    public Animal(string name)
    {
    Name = name;
    }

    public static void GetSum<T>(ref T num1, ref T num2)
    {
    double dblx = Convert.ToDouble(num1);
    double dbly = Convert.ToDouble(num2);
    Console.WriteLine($"{dblx} + {dbly} = {dblx + dbly}");
    }
    }
  • 结构体的泛型

    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
    public struct Rectangle<T>
    {
    private T width;
    private T height;

    public T Width
    {
    get { return width; }
    set { width = value; }
    }

    public T Height
    {
    get { return height; }
    set { height = value; }
    }

    public Rectangle(T w, T h)
    {
    width = w;
    height = h;
    }

    public string GetArea()
    {
    double dlbWidth = Convert.ToDouble(Width);
    double dlbHeight = Convert.ToDouble(Height);
    return String.Format($"{Width} * {Height} = {dlbWidth * dlbHeight}");
    }

    }
  • 调用

    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
    static void Main(string[] args)
    {
    List<Animal> animalList = new List<Animal>();
    List<int> intList = new List<int>();

    intList.Add(24);
    animalList.Add(new Animal("Dog"));
    animalList.Add(new Animal("Cat"));
    animalList.Add(new Animal("Bird"));

    animalList.Insert(1, new Animal("Duck"));
    animalList.RemoveAt(1);

    Console.WriteLine("Num of Animals : {0}", animalList.Count);
    foreach(Animal animal in animalList)
    {
    Console.WriteLine(animal.Name);
    }

    int x = 5, y = 4;
    Animal.GetSum<int>(ref x, ref y);
    string strX = "5", strY = "4";
    Animal.GetSum<string>(ref strX, ref strY);

    Rectangle<int> rec1 = new Rectangle<int>(20, 50);
    Console.WriteLine(rec1.GetArea());

    Rectangle<string> rec2 = new Rectangle<string>("20", "50");
    Console.WriteLine(rec2.GetArea());
    }

10 - Delegates

委托:如果我们想要将一个函数作为参数传递,C# 如何处理回调函数或事件处理程序?答案是 - 委托。 委托是一种引用类型数据类型,它定义了方法的签名。您可以像其他数据类型一样定义委托的变量,它可以引用与委托相同签名的任何方法。

在使用委托时涉及三个步骤:

  • 声明一个委托
  • 设置目标方法
  • 调用委托

可以使用 delegate 关键字后跟函数签名来声明委托,如下所示。

1
public delegate void MyDelegate(string msg);

以下是一个使用委托的例子:

  • 函数:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public delegate void Arithmetic(double num1, double num2);

    public static void Add(double num1, double num2)
    {
    Console.WriteLine($"{num1} + {num2} = {num1 + num2}");
    }

    public static void Subtract(double num1, double num2)
    {
    Console.WriteLine($"{num1} - {num2} = {num1 - num2}");
    }
  • 调用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Arithmetic add, sub, addSub;
    add = new Arithmetic(Add);
    sub = new Arithmetic(Subtract);
    addSub = add + sub;

    Console.WriteLine($"Add {6} & {10}");
    add(6, 10);

    Console.WriteLine($"Add & Subtract {10} & {4}");
    addSub(10, 4);

11 - Lambda

  • Basic

    1
    2
    doubleIt doubleIt = x => x * 2;
    Console.WriteLine($"5 * 2 = {doubleIt(5)}");
  • Where

    条件判断

    1
    2
    3
    4
    5
    6
    7
    8
    9
    List<int> numList = new List<int> { 1, 9, 2, 6, 3 };

    var evenList = numList.Where(a => a % 2 == 0).ToList();
    foreach (var j in evenList)
    Console.WriteLine(j);

    var rangeList = numList.Where(x => (x > 2) || (x < 9)).ToList();
    foreach (var k in rangeList)
    Console.WriteLine(k);

    生成列表

    1
    2
    3
    4
    5
    6
    7
    8
    List<int> flipList = new List<int>();
    int i = 0;
    Random rnd = new Random();
    while (i < 100)
    {
    flipList.Add(rnd.Next(1, 3));
    i++;
    }

    条件判断

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Console.WriteLine("Heads : {0}",
    flipList.Where(a => a == 1).ToList().Count());
    Console.WriteLine("Tails : {0}",
    flipList.Where(a => a == 2).ToList().Count());

    // Find all names starting with s
    var nameList = new List<string> { "Doug", "Sally", "Sue" };
    var sNameList = nameList.Where(x => x.StartsWith("S"));

    foreach (var m in sNameList)
    Console.WriteLine(m);
  • Select

    1
    2
    3
    4
    5
    6
    var oneTo10 = new List<int>();
    oneTo10.AddRange(Enumerable.Range(1, 10));
    var squares = oneTo10.Select(x => x * x);

    foreach (var l in squares)
    Console.WriteLine(l);
  • Zip

    1
    2
    3
    4
    5
    6
    7
    var listOne = new List<int>(new int[] { 1, 3, 4 });
    var listTwo = new List<int>(new int[] { 4, 6, 8 });

    var sumList = listOne.Zip(listTwo, (x, y) => x + y).ToList();

    foreach (var n in sumList)
    Console.WriteLine(n);
  • Aggregate

    1
    2
    3
    var numList2 = new List<int>() { 1, 2, 3, 4, 5 };
    Console.WriteLine("Sum : {0}",
    numList2.Aggregate((a, b) => a + b));
  • Average

    1
    2
    3
    4
    var numList3 = new List<int>() { 1, 2, 3, 4, 5 };

    Console.WriteLine("AVG : {0}",
    numList3.AsQueryable().Average());
  • All

    1
    2
    3
    4
    var numList4 = new List<int>() { 1, 2, 3, 4, 5 };

    Console.WriteLine("All > 3 : {0}",
    numList4.All(x => x > 3));
  • Any

    1
    2
    3
    4
    var numList5 = new List<int>() { 1, 2, 3, 4, 5 };

    Console.WriteLine("Any > 3 : {0}",
    numList5.Any(x => x > 3));
  • Distinct

    去掉重复项,输出独立结果

    1
    2
    3
    4
    var numList6 = new List<int>() { 1, 2, 3, 2, 3 };

    Console.WriteLine("Distinct : {0}",
    string.Join(", ", numList6.Distinct()));
  • Except

    1
    2
    3
    4
    5
    var numList7 = new List<int>() { 1, 2, 3, 2, 3 };
    var numList8 = new List<int>() { 3 };

    Console.WriteLine("Except : {0}",
    string.Join(", ", numList7.Except(numList8)));
  • Intersect

    1
    2
    3
    4
    5
    var numList9 = new List<int>() { 1, 2, 3, 2, 3 };
    var numList10 = new List<int>() { 2, 3 };

    Console.WriteLine("Intersect : {0}",
    string.Join(", ", numList9.Intersect(numList10)));

12 - IEnumerator

很多时候,我们需要循环遍历一个匿名类型的类或列表集合。C# 语言的 IEnumerable 接口是其中一个最好的功能,用于循环遍历集合。

C# 中的 IEnumerable 是一个接口,定义了一个方法 GetEnumerator,该方法返回一个 IEnumerator 接口。这允许对集合进行只读访问,然后实现 IEnumerable 接口的集合可以在 for-each 语句中使用。

  • 子类

    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
    internal class AnimalFarm : IEnumerable
    {
    private List<Animal> m_AnimalList = new List<Animal>();

    public AnimalFarm(List<Animal> animal)
    {
    m_AnimalList = animal;
    }

    public AnimalFarm() { }

    public Animal this[int index]
    {
    get { return m_AnimalList[index]; }
    set { m_AnimalList.Insert(index, value); }
    }

    public int Count
    {
    get { return m_AnimalList.Count; }
    }

    public IEnumerator GetEnumerator()
    {
    return m_AnimalList.GetEnumerator();
    }
    }
  • 遍历

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    AnimalFarm animalFarm = new AnimalFarm();
    animalFarm[0] = new Animal("Cat");
    animalFarm[1] = new Animal("Dog");
    animalFarm[2] = new Animal("Bird");
    animalFarm[3] = new Animal("Duck");

    foreach(Animal animal in animalFarm)
    {
    Console.WriteLine(animal.Name);
    }

13 - Operator Overloading

本章包括运算符重载以及方法重载

  • 运算符重载

    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
    public static Box operator + (Box box1, Box box2)
    {
    Box box = new Box()
    {
    Length = box1.Length + box2.Length,
    Width = box1.Width + box2.Width,
    Breadth = box1.Breadth + box2.Breadth
    };

    return box;
    }

    public static Box operator - (Box box1, Box box2)
    {
    Box box = new Box()
    {
    Length = box1.Length - box2.Length,
    Width = box1.Width - box2.Width,
    Breadth = box1.Breadth - box2.Breadth
    };

    return box;
    }

    public static bool operator ==(Box box1, Box box2)
    {
    if ((box1.Length == box2.Length) &&
    (box1.Width == box2.Width) &&
    (box1.Breadth == box2.Breadth))
    {
    return true;
    }
    return false;
    }

    public static bool operator !=(Box box1, Box box2)
    {
    if ((box1.Length != box2.Length) ||
    (box1.Width != box2.Width) ||
    (box1.Breadth != box2.Breadth))
    {
    return true;
    }
    return false;
    }
  • 方法重载

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public override string ToString()
    {
    return String.Format("Box with Height : {0} Width : {1} and Breadth : {2}",
    Length, Width, Breadth);
    }

    public static explicit operator int(Box b)
    {
    return (int)(b.Length + b.Width + b.Breadth) / 3;
    }

    public static implicit operator Box(int i)
    {
    return new Box(i, i, i);
    }
  • 调用

    1
    2
    3
    4
    5
    6
    7
    8
    Box box1 = new Box(2, 3, 4);
    Box box2 = new Box(5, 6, 7);
    Box box3 = box1 + box2;

    Console.WriteLine($"Box 3 : {box3}");
    Console.WriteLine($"Box int : {(int)box3}");
    Box box4 = (Box)4;
    Console.WriteLine($"Box 4 : {box4}");

需要注意的是方法重载中使用到了explicitimplicit,在 C# 中,使用隐式和显式运算符进行数据类型转换。

  • 隐式运算符用于在转换时无需用户干预的情况下将一种数据类型转换为另一种数据类型。
  • 显式运算符用于在转换可能导致数据丢失或无法保证成功时进行显式用户干预。

当转换无需数据丢失时,通常首选使用隐式运算符。隐式运算符用于使代码更简洁、易读。隐式运算符还用于经常执行的转换,例如:

1
2
int num1 = 10;
double num2 = num1; // 隐式转换

当转换可能导致数据丢失或无法保证成功时,通常首选使用显式运算符,例如:

1
2
double num1 = 10.5;
int num2 = (int)num1; // 显式转换

在之前的方法重载中,由于double往int重载会损失精度,因此使用显示运算符explicit

而后面的例子中,由于使用int作为参数生成一个Box对象,不会发生数据损失,因此使用隐式运算符implicit

14 - Anonymous Types

  • 匿名类型

    1
    2
    var shopkins = new { Name = "Shopkins", Price = 4.99 };
    Console.WriteLine("{0} cost ${1}", shopkins.Name, shopkins.Price);
  • 匿名类型数组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var toyArray = new[] 
    {
    new { Name = "Yo-Kai Pack", Price = 4.99 },
    new { Name = "Legos", Price = 9.99 }
    };


    foreach (var item in toyArray)
    {
    Console.WriteLine("{0} costs ${1}", item.Name, item.Price);
    }

15 - LINQ

语言集成查询 (LINQ) 是一系列直接将查询功能集成到 C# 语言的技术统称。 数据查询历来都表示为简单的字符串,没有编译时类型检查或 IntelliSense 支持。 此外,需要针对每种类型的数据源了解不同的查询语言:SQL 数据库、XML 文档、各种 Web 服务等。 借助 LINQ,查询成为了最高级的语言构造,就像类、方法和事件一样。

  • Data

    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
    Animal[] animalList = new[] 
    {
    new Animal{ Name = "German Shepherd", Height = 25, Weight = 77, AnimalID = 1 },
    new Animal{ Name = "Chihuahua", Height = 7, Weight = 4.4, AnimalID = 2 },
    new Animal{ Name = "Saint Bernard", Height = 30, Weight = 200, AnimalID = 3 },
    new Animal{ Name = "Pug", Height = 12, Weight = 16, AnimalID = 1 },
    new Animal{ Name = "Beagle", Height = 15, Weight = 23, AnimalID = 2 }
    };

    var animalEnum = animalList.OfType<Animal>();

    var selectedAnimal = from animal in animalEnum
    where animal.Weight <= 90
    orderby animal.Name
    select animal;

    foreach(var animal in selectedAnimal)
    {
    Console.WriteLine("{0} weight {1}lbs", animal.Name, animal.Weight);
    }



    Owner[] owners = new[]
    {
    new Owner{ Name = "Doug Parks", OwnerID = 1 },
    new Owner{ Name = "Sally Smith", OwnerID = 2 },
    new Owner{ Name = "Paul Brooks", OwnerID = 3 }
    };

    var nameHeight = from a in animalList
    select new
    {
    a.Name,
    a.Height
    };

    Array arrNameHeight = nameHeight.ToArray();

    foreach (var i in arrNameHeight)
    {
    Console.WriteLine(i.ToString());
    }

  • Join

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var innerJoin =
    from animal in animalList
    join owner in owners on animal.AnimalID
    equals owner.OwnerID
    select new { OwnerName = owner.Name, AnimalName = animal.Name };

    foreach (var i in innerJoin)
    {
    Console.WriteLine("{0} owns {1}",
    i.OwnerName, i.AnimalName);
    }
  • 复杂查询

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    var groupJoin = from owner in owners
    orderby owner.OwnerID
    join animal in animalList on owner.OwnerID
    equals animal.AnimalID into ownerGroup
    select new
    {
    Owner = owner.Name,
    Animals = from owner2 in ownerGroup
    orderby owner2.Name
    select owner2
    };

    int totalAnimals = 0;

    foreach (var ownerGroup in groupJoin)
    {
    Console.WriteLine(ownerGroup.Owner);
    foreach (var animal in ownerGroup.Animals)
    {
    totalAnimals++;
    Console.WriteLine("* {0}", animal.Name);
    }
    }

15 - Threads

  • 线程的基本使用方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    static void Print1()
    {
    for(int i = 0; i < 1000; i++)
    {
    Console.Write(1);
    }
    }

    static void Main(string[] args)
    {
    Thread thread = new Thread(Print1);
    thread.Start();
    for(int i = 0; i < 1000; i++)
    {
    Console.Write(0);
    }

    }
  • sleep

    1
    2
    3
    4
    5
    6
    7
    8
    int num = 1;
    for (int i = 0; i < 10; i++)
    {
    Console.WriteLine(num);
    Thread.Sleep(1000);
    num++;
    }
    Console.WriteLine("Thread Ends");
  • 锁的使用

    类:

    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
    internal class BankAcct
    {
    private Object acctLock = new Object();
    public double Balance { get; set; }
    public string Name { get; set; }

    public BankAcct(double balance)
    {
    Balance = balance;
    }

    public double Withdraw(double amount)
    {
    if(Balance - amount < 0)
    {
    Console.WriteLine($"Sorry ${Balance} in Account");
    return Balance;
    }
    lock(acctLock)
    {
    if(Balance >= amount)
    {
    Console.WriteLine("Remove {0} and {1} left in account", amount, (Balance - amount));
    Balance -= amount;
    }
    return Balance;
    }
    }

    public void IssueWithdraw()
    {
    Withdraw(1);
    }

    }

    用例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    BankAcct acct = new BankAcct(10);
    Thread[] threads = new Thread[15];

    Thread.CurrentThread.Name = "main";

    for(int i = 0; i < 15; i++)
    {
    Thread thread = new Thread(new ThreadStart(acct.IssueWithdraw));
    thread.Name = i.ToString();
    threads[i] = thread;
    }

    for (int i = 0; i < 15; i++)
    {
    Console.WriteLine("Thread {0} Alive : {1} ", threads[i].Name, threads[i].IsAlive);
    threads[i].Start();
    Console.WriteLine("Thread {0} Alive : {1} ", threads[i].Name, threads[i].IsAlive);
    }

    Console.WriteLine("Current Priority {0}", Thread.CurrentThread.Priority);
    Console.WriteLine("Thread {0} Ending", Thread.CurrentThread.Name);
  • 其他调用方法

    1
    2
    3
    4
    5
    6
    7
    8
    Thread thread = new Thread(() => CountTo(10));
    thread.Start();

    new Thread(() =>
    {
    CountTo(5);
    CountTo(6);
    }).Start();

17 - File I/O

Directory Functions

文件类用法:

包括识别文件信息、创建以及删除文件

1
2
3
4
5
6
7
8
9
10
11
12
13
DirectoryInfo currentDir = new DirectoryInfo(".");

Console.WriteLine(currentDir.FullName);
Console.WriteLine(currentDir.Name);
Console.WriteLine(currentDir.Parent);
Console.WriteLine(currentDir.Attributes);
Console.WriteLine(currentDir.CreationTime);

DirectoryInfo dataDir = new DirectoryInfo(@"E:\Code\Course\C#\CSharpTutorial\CSharpData");
dataDir.Create();
Console.WriteLine("Data Dir is Exists? : {0}", dataDir.Exists);

//dataDir.Delete();

FILE READING & WRITING

文件的读取以及写入:

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
string[] customers =
{
"Bob Smith",
"Sally Smith",
"Robert Smith"
};

string textFilePath = @"E:\Code\Course\C#\CSharpTutorial\CSharpData\testfile1.txt";
File.WriteAllLines(textFilePath, customers);

foreach (string cust in File.ReadAllLines(textFilePath))
{
Console.WriteLine($"Customer : {cust}");
}

DirectoryInfo myDataDir = new DirectoryInfo(@"E:\Code\Course\C#\CSharpTutorial\CSharpData");
FileInfo[] txtFiles = myDataDir.GetFiles("*.txt", SearchOption.AllDirectories);

Console.WriteLine("Matches : {0}", txtFiles.Length);

foreach (FileInfo file in txtFiles)
{
Console.WriteLine(file.Name);
Console.WriteLine(file.Length);
}

File Streams

使用文件流写入数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
string textFilePath = @"E:\Code\Course\C#\CSharpTutorial\CSharpData\testfile1.txt";
FileStream fileStream = File.Open(textFilePath, FileMode.Create);

string randString = "This is a random string";
byte[] randBytes = Encoding.Default.GetBytes(randString);
fileStream.Write(randBytes, 0, randBytes.Length);
fileStream.Position = 0;

byte[] fileByteArray = new byte[randBytes.Length];

for(int i = 0; i < randBytes.Length; i++)
{
fileByteArray[i] = (byte)fileStream.ReadByte();
}
Console.WriteLine(Encoding.Default.GetString(fileByteArray));
fileStream.Close();

StreamWriter/StreamReader

流读写,推荐使用

1
2
3
4
5
6
7
8
9
10
11
12
string textFilePath = @"E:\Code\Course\C#\CSharpTutorial\CSharpData\testfile1.txt";
StreamWriter sw = new StreamWriter(textFilePath);
sw.Write("This is a random ");
sw.WriteLine("sentence.");
sw.WriteLine("This is another sentence.");
sw.Close();

StreamReader sr = new StreamReader(textFilePath);
Console.WriteLine("Peek : {0}", Convert.ToChar(sr.Peek()));
Console.WriteLine("1st String : {0}", sr.ReadLine());
Console.WriteLine("Everything Else : {0}", sr.ReadToEnd());
sr.Close();

BinaryWriter/BinaryReader

二进制读写器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
string textFilePath = @"E:\Code\Course\C#\CSharpTutorial\CSharpData\testfile1.txt";
FileInfo fileInfo = new FileInfo(textFilePath);
BinaryWriter bw = new BinaryWriter(fileInfo.OpenWrite());
string randText = "Random Text";
int myAge = 0;
double height = 6.25;
bw.Write(randText);
bw.Write(myAge);
bw.Write(height);
bw.Close();

BinaryReader br = new BinaryReader(fileInfo.OpenRead());
Console.WriteLine(br.ReadString());
Console.WriteLine(br.ReadInt32());
Console.WriteLine(br.ReadDouble());
br.Close();

18 - Serialization

  • 可以被序列化的对象需要添加一些功能

    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
    [Serializable()]
    public class Animal : ISerializable
    {
    public string Name { get; set; }
    public double Weight { get; set; }
    public double Height { get; set; }
    public int AnimalID { get; set; }

    public Animal() { }

    public Animal(string name, double weight, double height, int id)
    {
    Name = name;
    Weight = weight;
    Height = height;
    AnimalID = id;
    }
    public override string ToString()
    {
    return string.Format("{0} weighs {1} lbs and is {2} inches tall",
    Name, Weight, Height);
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
    // Assign key value pair for your data
    info.AddValue("Name", Name);
    info.AddValue("Weight", Weight);
    info.AddValue("Height", Height);
    info.AddValue("AnimalID", AnimalID);
    }

    public Animal(SerializationInfo info, StreamingContext ctxt)
    {
    //Get the values from info and assign them to the properties
    Name = (string)info.GetValue("Name", typeof(string));
    Weight = (double)info.GetValue("Weight", typeof(double));
    Height = (double)info.GetValue("Height", typeof(double));
    AnimalID = (int)info.GetValue("AnimalID", typeof(int));
    }
    }
  • 使用序列化

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    Animal bowser = new Animal("Bowser", 45, 25, 1);
    Stream stream = File.Open("AnimalData.dat", FileMode.Create);
    BinaryFormatter bf = new BinaryFormatter();

    bf.Serialize(stream, bowser);
    stream.Close();

    bowser = null;

    stream = File.Open("AnimalData.dat", FileMode.Open);
    bf = new BinaryFormatter();
    bowser = (Animal)bf.Deserialize(stream);
    stream.Close();

    Console.WriteLine(bowser.ToString());

XMLSerialization

  • 单个对象的读写:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    DirectoryInfo dataDir = new DirectoryInfo(@"E:\Code\Course\C#\CSharpTutorial\CSharpData");
    if(!dataDir.Exists)
    dataDir.Create();

    Animal bowser = new Animal("Bowser", 45, 25, 1);
    XmlSerializer serializer = new XmlSerializer(typeof(Animal));
    using (TextWriter writer = new StreamWriter(@"E:\Code\Course\C#\CSharpTutorial\CSharpData\bowser.xml"))
    {
    serializer.Serialize(writer, bowser);
    }
    bowser = null;

    XmlSerializer deserializer = new XmlSerializer(typeof(Animal));
    TextReader reader = new StreamReader(@"E:\Code\Course\C#\CSharpTutorial\CSharpData\bowser.xml");
    object obj = deserializer.Deserialize(reader);
    bowser = (Animal)obj;
    reader.Close();

    Console.WriteLine(bowser.ToString());
  • 列表读写:

    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
    DirectoryInfo dataDir = new DirectoryInfo(@"E:\Code\Course\C#\CSharpTutorial\CSharpData");
    if (!dataDir.Exists)
    dataDir.Create();

    //Write List
    List<Animal> theAnimals = new List<Animal>
    {
    new Animal("Mario", 60, 30, 2),
    new Animal("Luigi", 55, 24, 3),
    new Animal("Peach", 40, 20, 4)
    };

    using (Stream fs = new FileStream(@"E:\Code\Course\C#\CSharpTutorial\CSharpData\bowser.xml", FileMode.Create, FileAccess.Write, FileShare.None))
    {
    XmlSerializer serializer2 = new XmlSerializer(typeof(List<Animal>));
    serializer2.Serialize(fs, theAnimals);
    }

    theAnimals = null;

    XmlSerializer serializer3 = new XmlSerializer(typeof(List<Animal>));

    using (FileStream fs2 = File.OpenRead(@"E:\Code\Course\C#\CSharpTutorial\CSharpData\bowser.xml"))
    {
    theAnimals = (List<Animal>)serializer3.Deserialize(fs2);
    }


    foreach (Animal a in theAnimals)
    {
    Console.WriteLine(a.ToString());
    }