---
# System prepended metadata

title: C# 學習筆記 | 基礎
tags: [學習筆記, C#]

---

###### tags: `C#` `學習筆記` 
# C# 學習筆記 | 基礎
## 知識
### 輸出
```csharp!
Console.WriteLine(); // 輸出，換行
Console.Write(); // 輸出，不換行
```
### 作用域
變數只在 **{}** 生效
```csharp!
int a = 10;
if(true)
{
    int b = 20;
}
Console.WriteLine(a); // 10
Console.WriteLine(b); // 報錯
```
### 流程控制
```csharp!
//----- if
if(<boolean_expression>)
{
   statement(s);
}
else
{
  statement(s);
}

//----- switch
switch(<expression>)
{
    case <constant-expression>:
       statement(s);
       break; 
    case <constant-expression>:
       statement(s);
       break; 
    default : /* 可選的 */
       statement(s);
       break; 
}
```
### 迴圈
```csharp!
//----- for
for( init; condition; increment )
{
   statement(s);
}

//----- while
while(<condition>)
{
   statement(s);
}

//----- do while，一定先執行一次
do
{
   statement(s);
} while(<condition>)
```


## 變數
![](https://hackmd.io/_uploads/r1cuhfoUh.jpg)
### 強轉換
```csharp!
string str = "20";
int num = 20;
//----- 轉換為 int
int a = (int)str;
int b = Convert.ToInt32(str);
int c = int.Parse(str)
    
//----- 轉換為 string
string str = num.ToString();
```
### dynamic 動態
在聲明時會以賦予值類型來決定是什麼類型
```csharp!
dynamic a = 20;
dynamic b = "20";
dynamic c;
c = b + a;
Console.WriteLine(a + 20); // 40
Console.WriteLine(b + 20); // 2020
Console.WriteLine(c); // 2020
```

### const | readonly
`const` 和 `readonly` 的很相似，都是不能更改的變數

`const` 更加嚴格，他在聲明後就必須賦值，
```csharp!
const double PI = 3.14;
const int a = 20; // 會報錯
```
與之相比，`readonly` 可以先聲明，之後再賦值，但要注意的是 readonly 只能在構造函數(建構子)中賦值，不能在一般函數內賦值
```csharp!
internal class Airplane : IFly
 {
     private readonly int A;
     public Airplane(int a) { A= a; }
     public void Fly()
     {
         Console.WriteLine("飛機起飛了");
         A = 20; // 會報錯
     }
}
```


## String
### ""
```csharp!
1. string str = "c:\\file\\program"; // 特殊字符必須使用反斜線
2. string str = @"c:\file\program"; // 可以使用反斜線
3. string str = $"我的名字是{name}"; // 可以串接          
```
### 常用函數
```csharp!
string web = "www.google.com";
string str = " Hi I am Zeke. "
    
str.ToLower() // 全轉換大寫
str.ToUpper() // 全轉換小寫
str.Trim() // 修剪前後空白
str.CompareTo(web) // 0==true, 1==false 
str.Replace("ek", "a")) // replace all
str.Substring(0, 2) // " H" 切頭切尾
web.Split(".") // ["www", "google", "com"]
web.IndexOf(".") // 3
web.IndexOfAny(new char[] { 'z', 'g' }) // 搜索index，沒有就接續後面陣列的數字
web.Insert(0, "???")  // ???www.google.com 
    
//----- CopyTo()
char[] cArr = new char[10];
str.CopyTo(1, cArr, 1, 4); // 複製目標第1索引開始共4個char，到cArr第1索引
// [' ', 'H', 'i', ' ', 'I']

//----- 使用 String class
int c = 2;
int d = 8;
string.Concat(web, str) // a + b, www.google.com Hi I am Zeke. 
string.Format("{0} + {1} = {2}", c, d, c + d) //2 + 8 = 10
string.Format("{0:C}", d)); // c 使用貨幣，NT$8.00
string.Format("{0:F2}", 33.2259) // f(n) 保留後面小數共n位，33.23
string.Format("{0:P}", 0.25259) // 百分比，25.26%
```
### StringBuilder
一般的**string**是儲存在靜態儲存區中，更改過後會新增新的字串，不會對原來的數據進行變化，而是返回更改過後的字串

string builder 會以陣列的方式儲存在**堆(heap)**中，所以會更改最原本的字串

所以如果字串有頻繁的操作，才會使用string builder
```csharp!
StringBuilder sb = new StringBuilder("i am Zeke.");

sb.Append(" No, you are not Zeke."); // push()
sb.Insert(1, "--"); 
sb.Remove(4, 2);
sb.Replace(" ", "--");

Console.WriteLine(sb);
```


## Array
### 基礎
```csharp!
// 聲明
int[] arr1 = {1, 2, 3};
int[] arr2 = new int[2] {1,2};

// 長度
Console.WriteLine(arr.Length);
```
### 遍歷
```csharp!
int[] arr = {1, 2, 3, 4, 5};
foreach(int item in arr)
{
    // 1 2 3 4 5，如同 arr.foreach((item) => {})
    Console.WriteLine(item) 
}
```

## enum 枚舉
在 class 內聲明枚舉

每個枚舉都有相對應的 index number，可自訂index，定義後面沒定義的會跟隨前面的index
```csharp!
namespace HelloWorld
{
    class Program
    {
        enum RoleType
        {
            Tank = 10, 
            Warrior, // 11
            Mage = 30, 
            Assassin, // 31 
            Archer
        }
        static void Main(string[] args)
        {
            RoleType player1 = RoleType.Assassin; 
            RoleType player2 = RoleType.Tank; 
        }
    }
}
```



## struct 結構
簡易版的 class，需要實例化 `new`
```csharp!
namespace HelloWorld
{
    class Program
    {
        struct StudentInfo 
        {
            public int id;
            public string name;
            public int age;
            private int adress;

            public void PrintStudentInfo()
            {
                Console.WriteLine($"名字:{name}");
            }
        }
        static void Main(string[] args)
        {
            StudentInfo[] students = new StudentInfo[10];
            students[0].name = "Zeke";
            students[0].age = 24;
            students[0].id = 88965;
            students[0].PrintStudentInfo();
        }
    }
}
```


## delegate 委託

可以引用擁有相同**params**和**返回值**的函數，這讓使用函數更加的簡便
```csharp!
delegate void IntMethodInvoker(int i);
public static void Main(string[] args)
{
    IntMethodInvoker invoker = null;
    invoker = Test;
    invoker(20);
    invoker = Test2;
    invoker(22);
}
private void Test(int i) {}
private void Test2(int i) {}

```

可以指向任一類別的靜態(static)函數，如同Object類別的ToString()
```csharp!
delegate string GetString();
public static void Main(string[] args)
{
    int a = 666;
    GetString invoker2 = a.ToString;
    Console.WriteLine(invoker2() + 222); //666222
}
```

也可以指定成陣列型態的委託，讓訂閱和發佈的設計模式得以實現
```csharp!
delegate double MathDelegate(double i);
public void  Main()
{
    MathDelegate[] operation = { 
	MathOperator.Square, // 平方的函數 
	MathOperator.MutipllyByTwo // 相加的函數
    };
    Console.WriteLine(operation[0](5.5)); // 30.25    
}

```
### Action<> | Func<>
這Action 和 Func 本質上是簡短寫法的委託
#### 1. Action<>
返回值為 **void**，參數可以任意多個，也可以為無，但返回值必定 void
```csharp!
public static void Main()
{
    Action ac1 = AC1;
    Action<int, string> ac2 = AC2;
}
private static void AC1(){};
private static void AC2(int a, string b) {}
```
#### 2. Func<> 
必須要有返回值，參數可以任一多個，且最後一個參數必定為返回值
```csharp!
public static void Main()
{
    Func<string> f1 = FC1;
    Func<int, int, int> f2 = FC2;
}
private static string FC1()
{ return "Google"};
private static int FC2(int a, int b) 
{ return a + b }
```


## 匿名函數 | Lambda
匿名函數允許直接在函數體內制定另一函數，通常是式子簡短的普通計算為主
```csharp!
Func<int, int, int> plus = delegate (int a, int b)
{
    int result = a + b
    return result;
};
```
### Lambda
更簡寫的匿名函數，就是 JS的箭頭函數
```csharp!
Func<int, int, int> plus = (a, b) => { return a + b;};

Func<int, int> quare = a => a * a;
```
