###### tags: `C#`
# **C#實作課程-Lesson 4**
# 列舉 enum
# 類別的繼承
## 基底類別(父類別) vs 衍生類別(子類別)
語法: 衍生類別:基底類別
●衍生類別只能繼承1個基底類別
●如果程式碼不複雜,可將基底類別與其衍生類別寫在同一個檔案(.cs)
```csharp=
public enum LogTypeDef
{
SystemError,Error,Information
}
public class Log
{
public LogTypeDef LogType { get; set; }
public string LogContent { get; set; }
public DateTime LogTime { get; set; }
public string MailAddr { get; set; }
public void WriteLog()
{
if (this.LogType ==LogTypeDef.SystemError)
Console.WriteLine($"send email to{MailAddr}");
Console.WriteLine(LogContent);
}
}
public class dbLog:Log
{
public void WritLog()
{
Console.WriteLine(MailAddr);
}
}
public class txtLog:Log
{
}
```
# override(複寫) vs method hiding(方法遮蔽)
●基底類別&衍生類別可使用相同名稱與參數的方法,分為下列兩種使用方式
override(複寫)
```csharp=
public class Log
{
public LogTypeDef LogType { get; set; }
public string LogContent { get; set; }
public DateTime LogTime { get; set; }
public string MailAddr="abcd@gmail.com";
public virtual void WriteLog()//父類別使用virtual關鍵字
{
if (this.LogType == LogTypeDef.SystemError)
Console.WriteLine($"send email to: {MailAddr}");
Console.WriteLine($"Base Log Show: {this.LogContent}");
}
}
public class dbLog : Log
{
public override void WriteLog()//子類別使用override關鍵字
{
Console.WriteLine(MailAddr);
}
}
```
執行下列相同程式碼差異:
```csharp=
class Program
{
static void Main(string[] args)
{
Log log1 = new dbLog();
Log log2 = new txtLog();
log1.WriteLog();
log2.WriteLog();
Console.ReadLine();
}
}
```

※基底類別可用來統整衍生類別,ex:List<T>
```csharp=
static void Main(string[] args)
{
Log log1 = new dbLog();
Log log2 = new txtLog();
var logs = new List<Log>();
logs.Add(log1);
logs.Add(log2);
foreach (var item in logs)
{
item.WriteLog();
}
Console.ReadLine();
}
```
執行效果相同↓

***********************************************
method hiding(方法遮蔽)
```csharp=
public class Log
{
public LogTypeDef LogType { get; set; }
public string LogContent { get; set; }
public DateTime LogTime { get; set; }
public string MailAddr { get; set; }
public void WriteLog()//父類別無關鍵字
{
if (this.LogType == LogTypeDef.SystemError)
Console.WriteLine($"send email to{MailAddr}");
Console.WriteLine(this.LogContent);
}
}
public class dbLog : Log
{
public new void WriteLog()//子類別使用new關鍵字,不寫也會視為父類別方法遮蔽
{
Console.WriteLine(MailAddr);
}
```
執行下列程式碼差異:
```csharp=
class Program
{
static void Main(string[] args)
{
Log log1 = new dbLog();
Log log2 = new txtLog();
log1.WriteLog();
log2.WriteLog();
Console.ReadLine();
}
}
```

# 介面 Interface
## 介面是一種類別,原則上僅有規格內容,不會有方法實作(類似公版的概念)
```csharp=
public interface IPay
{
int Cal(int money);
}
```
### 說明:
1.介面的命名:原則上會在前面加上"I"

2.介面定義好後,除非必要,否則不應該再修改
3.如果一個類別繼承了介面,就必須依照介面的規格去撰寫(包含方法名稱與參數)
※可避免例如共同開發時,各自撰寫方法、參數等等不一致
```csharp=
public class StoreA:IPay
{
public int Cal(int money)
{
if (money >= 5000)
{
return money;
}
return money + 100;
}
}
```
4.一個Class可以繼承多個interface,使用","區隔,同時也可以繼承基底類別
ex:
```csharp=
public class StoreA:IPay,IPay2,IPay3
{
}
```
ex:
```csharp=
public class StoreA:BClass,IPay,IPay2,IPay3
{
}
```
練習-interface實作
```csharp=
class Program
{
static void Main(string[] args)
{
var Customer1 = new Customer();
Customer1.StorePay = new StoreA();
Console.WriteLine(Customer1.StorePay.Cal(5000));
Console.ReadLine();
}
}
```
```csharp=
public class Customer
{
public string Name { get; set; }
public IPay StorePay { get; set; }
}
```
練習-interface建立(多種登入方式)
```csharp=
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter Login Type:(1:FB,2:LINE,3:Google)");
var authtype = Console.ReadLine();
var auth = new UserAuth();
switch (authtype)
{
case "1":
auth.DoLogin(new FBLogin());
break;
case "2":
auth.DoLogin(new LineLogin());
break;
case "3":
auth.DoLogin(new GoogleLogin());
break;
}
Console.ReadLine();
}
}
```
```csharp=
public class UserAuth
{
public void DoLogin(ILogin login)
{
login.Login();
}
}
```
```csharp=
public interface ILogin
{
bool Login();
}
```
```csharp=
public class FBLogin : ILogin
{
public bool Login()
{
Console.WriteLine("Do FB Login");
return true;
}
}
public class LineLogin : ILogin
{
public bool Login()
{
Console.WriteLine("Do Line Login");
return true;
}
}
public class GoogleLogin : ILogin
{
public bool Login()
{
Console.WriteLine("Do Google Login");
return true;
}
}
```
# 純文字txt檔案輸出、寫入、複製
## 輸出
```csharp=
Path.Combine() //將字串合併為路徑
```
```csharp=
File.ReadAllText(string path) //讀取檔案的所有文字,回傳string
```
```csharp=
File.ReadAllLines(string path) //讀取檔案所有行,回傳string[]
```
範例:

```csharp=
using System.IO;
public class FileAccessDemo
{
public static void ReadFile()
{
string filepath = Path.Combine(@"C:\Users\User\Documents", "Demo.txt");
string text = File.ReadAllText(filepath);
Console.WriteLine("Txt Contents:{0} !!!", text);
Console.WriteLine("====================分隔線====================");
string[] lines = File.ReadAllLines(filepath);
foreach (string line in lines)
{
Console.WriteLine("\t" + line);
}
Console.ReadLine();
}
}
```
```csharp=
class Program
{
static void Main(string[] args)
{
FileAccessDemo.ReadFile();
Console.ReadLine();
}
}
```

-
## 寫入
```csharp=
File.AppendAllLines(string path,string[]);//將字串陣列內容加在路徑檔案內容後方,不會覆寫
```

```csharp=
File.WriteAllLines(string path,string[]); //將路徑檔案內容全部覆寫掉
```

```csharp=
public static void Write()
{
string filepath= Path.Combine(@"C:\Users\User\Documents", "Demo.txt");
string[] lines = { "ABCDEFG", "HIJKLMN", "OPQRSTU", "VWXYZ" };
File.WriteAllLines(filepath, lines);
File.AppendAllLines(filepath, lines);
}
```
```csharp=
static void Main(string[] args)
{
FileAccessDemo.Write();
Console.ReadLine();
}
```
## 複製
```csharp=
//將路徑1檔案複製到路徑2檔案
//如果路徑2檔案已經存在,預設為不能覆寫(false)
File.Copy(string path1, string path2);
```

```csharp=
//將路徑1檔案複製到路徑2檔案
//如果路徑2檔案已經存在,可設定是否能覆寫(true:能覆寫 false:不能覆寫)
File.Copy(string path1, string path2,bool overwrite);
```
```csharp=
public static void Copy()
{
string filepath = Path.Combine(@"C:\Users\User\Documents", "Demo.txt");
string targetfilepath= Path.Combine(@"C:\Users\User\Documents", "DemoCopy.txt");
File.Copy(filepath, targetfilepath, true);//可覆寫目標路徑檔案
File.Copy(filepath, targetfilepath, false);//不可覆寫,故執行會失敗
//設定不可覆寫仍要能執行的方法:
//if (File.Exists(targetPath))
//{
// File.Delete(targetPath);
//}
//File.Copy(filePath, targetPath, false);
}
```
```csharp=
static void Main(string[] args)
{
FileAccessDemo.Copy();
Console.ReadLine();
}
```
## 使用FileInfo + StreamReader輸出
```csharp=
public class FileInfoAccess
{
public static void ReadFile()
{
string filepath = Path.Combine(@"C:\Users\User\Documents", "Demo.txt");
FileInfo myfile = new FileInfo(filepath);
using (StreamReader sr= myfile.OpenText())
{
var str = string.Empty;
while ((str=sr.ReadLine())!=null)
{
Console.WriteLine(str);
}
}
}
}
```
## 使用FileInfo + StreamWriter寫入
```csharp=
public static void Write()
{
string filepath = Path.Combine(@"C:\Users\User\Documents", "Demo.txt");
FileInfo myfile = new FileInfo(filepath);
string[] lines = { "ABCDEFG", "HIJKLMN", "OPQRSTU", "VWXYZ" };
using (StreamWriter sw=myfile.CreateText()) //覆寫路徑檔案內容
{
foreach (var item in lines)
{
sw.WriteLine(item);
}
}
using (StreamWriter sw = myfile.AppendText()) //內容新增在路徑檔案後方
{
foreach (var item in lines)
{
sw.WriteLine(item);
}
}
}
```
## 使用FileInfo複製
```csharp=
public static void Copy()
{
string filepath = Path.Combine(@"C:\Users\User\Documents", "Demo.txt");
string targetfilepath = Path.Combine(@"C:\Users\User\Documents", "DemoCopy.txt");
FileInfo File1 = new FileInfo(filepath);
if (!File1.Exists)
{
return;
}
else
{
FileInfo File2 = new FileInfo(targetfilepath);
if (File2.Exists)
{
File2.Delete();
}
File1.CopyTo(targetfilepath);
}
}
```