---
# System prepended metadata

title: C# 共筆
tags: [C#, NCNU]

---

C# 共筆
===
###### tags: `NCNU` `C#`

## Input

`Console.ReadLine()`: 讀取一行

### 空格格開多個輸入值
```csharp=
string text = Console.ReadLine();
string[] storage = text.Split(' ');

ex:
a = int.Parse(storage[0]);
b = int.Parse(storage[1]);
c = int.Parse(storage[2]);
```
#### 簡寫
```csharp=
int[] allNum = Array.ConvertAll(Console.ReadLine().Split(' '), int.Parse);
```

#### Another split example(delimiters)
source: [link](https://syntaxdb.com/ref/csharp/string-split)
```csharp=
    Console.Write("Please input 3 integers: ");
    string str = Console.ReadLine();
    char[] delimiters = {' '};
    //char[] delimiters = {' ', ','}; // split by space & comma
    string[] Array = str.Split(delimiters); //will split names using space as delimiter
    int[] myinteger = new int[Array.Length];
    int i = 0,total = 0;
    while (i < Array.Length)
    {
        myinteger[i] = Int32.Parse(Array[i]);
        total += myinteger[i];
        Console.WriteLine("{0}", myinteger[i]);
        i++;
    }
```


## Output
```csharp=
Console.WriteLine("xxx {0}", var);
Console.Write("xxx");
```

## File 讀寫
### 讀檔

```csharp=
using System.IO;
// System.Text.Encoding.Default 避免亂碼
StreamReader sr = new StreamReader("input.txt", System.Text.Encoding.Default);
// 檔案要放在 專案 /bin/debug 中 (若有 release 也要放一份), mac 好像要放在專案裡面

// 在很短的情形 fr.ReadToEnd() 與 fr.ReadLine() 相同

string readin;
while(!sr.EndOfStream)
{
    readin = sr.ReadLine();
}
sr.Close();
```
:::warning
檔案讀取如果沒有說幾行
每一行後面加個空白, 最後一筆換行
ex:
```
// input.txt

xxx 80 90
yyy 75 68
zzz 74 35
```
```csharp=
string readin = "";
while(!sr.EndOfStream)
{
    readin += sr.ReadLine() + " ";
}
Console.WriteLine(readin);
// xxx 80 90 yyy 75 68 zzz 74 35
```
:::

### 寫檔
```csharp=
StreamWriter sw = new StreamWriter("Output.txt");
sw.WriteLine("xxx");
sw.Close();
```

## Format
### Type
#### Array
```csharp=
int[] myArr = new int[100];
int[] myArr = new int[] {1, 2, 3};
```
2DA
```csharp=
int[,] myArr = new int[5, 10];
/* 不規則陣列 */ int[][] myjag = new int[3][];
int[][] myArr = new int [5][10];
int[,] myArr = new int[] {{1, 2}, {1, 2}, {1, 2}};
```
陣列初始化
```csharp=
int []a = new int []{1,2,3,5,6};
int [,]a = new int []{{1,2,3},{4,5,6},{7,8,9}};
string[] RoleName = new string[] {"魯夫","喬巴"};
```
> 連續記憶體空間
> [name=Array Memory]
---

#### ArrayList
- 一般使用方法
```csharp=
using System.Collections;
/* 需引入 System.Collections方可使用AraryList*/

/* Main 內*/
ArrayList myarraylist = new ArrayList();
for (int i = 0; i < 10; i++)
{
    myarraylist.Add(i);
}
// 0 1 2 3 4 5 6 7 8 9
myarraylist[myarraylist.Count/2] = 26;
// 0 1 2 3 4 26 7 8 9
Console.WriteLine("現在的長度:{0}", myarraylist.Count);
// 長度:10
for (int i = 0; i < myarraylist.Count; i++)
    Console.Write("{0} ", myarraylist[i].ToString().PadLeft(3));

myarraylist.RemoveAt(3);
// 0 1 2 4 26 7 8 9

myarraylist.Remove(2);
// 0 1 4 26 7 8 9

myarraylist.Insert(6,200);
// 0 1 4 26 7 8 200 9
```
- 存Structor到ArrayList
```csharp=
/*
 * ArrayList可存任何形態
 * Array宣告int則只可塞入int。
 */
 
/*
 * 塞入Structor範例
 */

public struct Personal
{
    public int age;
    public string name;
}

// ...
// ...
// ...
ArrayList myarraylist02 = new ArrayList();

for (int i = 0; i < 10; i++)
{
    Personal anyperson;
    anyperson.age = i + 50;
    anyperson.name = (i + 100).ToString();
    myarraylist02.Add(anyperson);
}

for (int i = 0; i < myarraylist02.Count; i++)
{
    Personal temp = (Personal)myarraylist02[i];
    Console.Write("\nname={0} ,age={1}", temp.name, temp.age);
}
```

#### foreach
```csharp=
int[] grade = new int[] {10, 20, 30};
foreach(int value in grade){
    ...
}
```

##### Function Of Array
---
- GetUpperBound() : index最大值
    - int [] a1 = new int [10];
        - a1.GetUpperBound() : 取第1維index // get 9
    - int [,] a2 = new int [3,3];
        - a2.GetUpperBound() : 取第2維index // get 2
- GetLowerBound()
- GetLength()
- CreateInstance()
- SetValue()
- GetValue()

---

> Example:
```csharp=
...bla...bla...bla...
static void Main(string[] args)
{
    int[] array_name = new int[100];
    int i;

    for (int i = 0; i < array_name.Length; i++)
        array_name[i] = i;

    for (int j = 0; j < array_name.Length; j++)
        Console.WriteLine("{0}", array_name[j]);

    Console.WriteLine("請按任意按鍵...");
    Console.ReadKey();
}

``` 


### string method
`{var}.toString('格式')`
> Example:
> method:one:
```csharp=
float fnum = -3.14f;
fnum.toString('0.0000'); // -3.1400
```
> method:two:
```csharp=
float fnum = -3.14f;
Console.WriteLine({0:0.0000},fnum); //-3.1400
```
#### 輸出其他格式
```csharp=
int num = 1234.567;
Console.WriteLine("numC={0:C} numC3={0:C3}", num, num);
// numC=NT$1,234.57 numC3=NT$1,234.567
```
參考課本 2-32, 2-33


#### 型態強制轉型(cast)
```csharp=
float a = 1.8f;
int i = (int)a;

/* 若要處理四捨五入 */
int i = (int)(a + 0.5);
```

## 自訂類別列舉常數 enumalte
> int 預設為 0 開始，後續+1...，如果中間更改常數值，後面不給定值會接續更改後的數值

```csharp=
enum WeekDays:int
{
 Monday = 1; //default with 0, but now defined with 1, so it's 1.
 Tuesday, // due to Monday = 1, monday++ then Tuesday = 2
 Wednesday,
 Thursday = 9,
 Friday, // due to Thursday = 9, Thursday++ then Friday = 10
 Saturday,
 Sunday
};

staic void main(string[] args)
{
    Console.WriteLine("星期一列舉常數值:{0}",(int)WeekDays.Monday);
    // 星期一列舉常數值:1
}
```
:::info
[Ref::M$::enum](https://docs.microsoft.com/zh-tw/dotnet/csharp/language-reference/keywords/enum)
:::


## 結構 Struct
```csharp=
// 預設不加 public, 預設為 private
// 
// 
// 
private struct StudentGrade
{
    // 裡面一定要加public, 否則外部無法修改
    public int math;
    public int program;
    public int total;
    public float average;
}
static void Main(string[] args)
{
    StudentGrade t1;
    Console.WriteLine("請輸入數學成績:");
    t1.math = Int32.Parse(Console.ReadLine());
    
    Console.WriteLine("請輸入程設成績:");
    t1.prog = Int32.Parse(Console.ReadLine());
    
    t1.total = t1.math + t1.prog;
    t1.average = t1.total / 2.0f;
    
    Console.WriteLine("數學:{0}, 程設:{1}, 總分:{2}, 平均:{3}", t1.math, t1.prog, t1.total, t1.average);
}
```

#### new
```csharp=
StudentGrade allStu;

StudentGrade[] allStu = new StudentGrade[100];
```

## if-else
:::danger
C# 無法使用這種寫法，編譯會錯誤!!

```csharp=
int k = 10;
if(k){
    ...
}
```
:::

## switch
可整數、"字串"、'字元'，
:warning:不可浮點數

## 比大小
可用 `Int32.MaxValue` 來獲得最大的值，反之可以加上負號
```csharp=
max = -Int32.MaxValue; // 任意比它大
min = Int32.MaxValue; // 任意比它小

...比大小...
```

### Array
```csharp=
Array.Sort(allNum);
int minV = allNum[0];
int maxV = allNum[allNum.Length - 1];

// or
Array.Reverse(allNum);
maxV = allNum[0];
```

## call by reference
```csharp=
public static void swap(ref int n1, ref int n2) {
    int tmp = n1;
    n1 = n2;
    n2 = tmp;
}

static void Main(string[] args) {
    int n1 = 10, n2 = 20;
    swap(ref n1, ref n2);
}
```

:::danger
記得傳址時，變數要有初始值，所以不能這樣:
```csharp=
int n3;
addTen(ref n3); // 錯誤，沒有初始值
```
:::

## 函數多載
允許同名 function overload，也解決命名煩惱。

雖然函數同名，但能透過傳入的參數數量辨別。

```csharp=
public static double Add(double a, double b)
{
  return (a + b);
}

public static double Add(double a)
{
  return a + 10.0;
}
```

## Try Catch
```csharp=
try
{
    ...
}
catch (SystemException ex)
{
    Console.WriteLine("錯誤訊息:{0}", ex.Message);
    Console.WriteLine("哪裡出問題:{0}", ex.StackTrace);
    Console.WriteLine("問題類別:{0}", ex.GetType().ToString());
    Console.WriteLine("source:{0}", ex.Source);
}
finally
{
    ...
}
```

### 檢查運算是否 overflow
**checked** 關鍵字是用來明確啟用整數型別算術運算和轉換的溢位檢查。

```
try
{
    a = checked(a * 10);
}
catch(SystemException ex)
{
    Console.WriteLine("\n----------------\n{0}", ex.StackTrace);
    Console.WriteLine("\n{0}\n----------------\n", ex.Message);
}
```

## 物件導向
```csharp=
public class ThreeNPlusOne
{
    int N;
    int count;
    /*
     * private int num0;
     * 若前有'private'則將無法透過在Main()內以ThreeNPlusOne.num呼叫
     * 可透過以下方式取得
     * public void getNum() {
           Console.Write(num);
       }
     * 
     * public int num1;
     * 前面為public則可直接以ThreeNPlusOne.num1進行存取。
     * 
     * protected int num2;
     * 
     * int num3; //預設為private
     * 
     * public double IN_Degree
        {
            set
            {
                in_degree = value;
            }
            get
            {
                return in_degree;
            }
        }
     */
    public void ShowResult()
    {
        Console.WriteLine("\nN = {0}, 執行 {1} 次", N, count);
    }
    public void Process()
    {
        int originN = N;
        while (N != 1)
        {
            count++;
            if (N % 2 == 0)
            {
                N /= 2;
            }
            else
            {
                N = 3 * N + 1;
            }
        }
        N = originN;
    }
    // Constructor 跟類別同名，不能有 return
    public ThreeNPlusOne()
    {
        N = 0;
        // this.N = 0;
        count = 0;
        // this.count = 0;
    }
    public ThreeNPlusOne(int n)
    {
        N = n;
        count = 0;
    }
}

static void Main(string[] args)
{
    Console.Write("請輸入正整數: ");
    int N = int.Parse(Console.ReadLine());
                
    ThreeNPlusOne a1 = new ThreeNPlusOne(N);
    
    a1.Process();
    a1.ShowResult();
}
```

### 白手套(?
避免使用者直接操作到私有變數，可以設立一個對外的變數(中介層)，透過對它的操作來更動私有變數。

```csharp=
public class Test
{
    private int money = 0;
    // protect private Data
    public int IN_money
    {
        set
        {
            if(value >= 0)
            {
                money = value;
            }
        }
        get
        {
            return money;
        }
    }
}
...
Test t1 = new Test();
t1.IN_money = 60;
```

:::info
``value`` 為關鍵字，取到的值為 main 函數中設定的值。

ex:
```
t1.out_var = 123;

// value = 123
```
:::

## 結尾/雜物
```csharp=
Console.WriteLine("請按任意鍵繼續...");
Console.ReadKey();
```

## Destructor
```csharp=
/*只有一種Destructor，清除佔用的記憶體*/
~ThreeNPlusOne()
{
    Console.WriteLine("This is a destructor....");
}
```

## 繼承
```csharp=
public class A
{
    public int x;
    private int y;
    protected int z;
    public A(int a, int b, int c)
    {
        x = a;
        y = b;
        z = c;
    }
    public void Show()
    {
        Console.WriteLine("x={0}, y={1}, z={2}",x , y, z);
    }
}

// B 繼承至 A
public class B : A
{
    public int w;
    public B(int a, int b, int c, int d)
        : base(a, b, c)
    {
        w = d;
    }
}
static void Main(string[] args)
{
    B objb = new B(10, 20, 30, 40);
    /*
     * B -> w = 40
     * A -> a = 10, b = 20, c = 30
     * 如同 java 内，public class B extends A;
     */
    objb.Show();  // 10,20,30,40
    objb.x = 100; // success: x 是 public
    objb.Show();  // 100,20,30,40
    objb.y = 200; // error: y 是 private
    objb.z = 300; // error: z 是 protected，下方有 success 例子。
}
```
==B繼承A，且可使用A's protected==
```csharp=
public class A
{
    public int x;
    private int y;
    protected int z;
    public A(int a, int b, int c)
    {
        x = a;
        y = b;
        z = c;
    }
    public void Show()
    {
        Console.WriteLine("x={0}, y={1}, z={2}",x , y, z);
    }
}

// B 繼承至 A
public class B : A
{
    public int w;
    public B(int a, int b, int c, int d)
        : base(a, b, c)
    {
        w = d;
    }
    static void Main(string[] args)
    {
        B objb = new B(10, 20, 30, 40);
        objb.z = 300; // success: z 是 protected，且在 B 内處理。
        objb.Show();  // 10,20,300,40
    }
}
```

繼承後也可以 override 原屬性/方法
```csharp=
public class A
{
    public void Show()
    {
        Console.WriteLine("Parent");
    }
}

// B 繼承至 A
public class B : A
{
    // override Parent's method
    new public void Show()
    {
        Console.WriteLine("Child");
    }
}
```