分類 CSharp-and-Dotnet 中的文章

C#: 元組 (Tuple)

因為隔壁介紹原則的部分有點卡住了,所以這週來紀錄一下挺常用到的方便東西:Tuple

這篇的 Tuple 指的是 C# 7.0 後提供的 ValueTuple 和相關語法,舊版得用 Tuple.Create 建立,成員的名稱也只能使用 Item1, Item2…,實用性並不是很高。但新 Tuple 出現後,方便程度大大提升,這邊就稍作紀錄一下。

註:此處使用的 Dump 是 Linqpad 提供的輸出方法,把它當成 Print 就行了。

var student = (1, "王小明");
student.Item1.Dump(); // 1
student.Item2.Dump(); // 王小明

student.Dump();

可以看到 Tuple 的建立相當簡單,只需要用小括號 () 括選起來即可。建立後的內容就會像這樣:

但這樣使用就和之前一樣,取出來時只能拿 Item1, Item2,放個幾天根本就不記得 Item1 裡面是啥東西了。這時我們就可以替成員們取名字

(int ID, string Name) student = (1, "王小明");
student.ID.Dump(); // 1
student.Name.Dump(); // 王小明

如此使用的時候就和一般操作物件的習慣沒有差別,也增加了可讀性。

……

閱讀全文


C#: 時區轉換、民國西元、國曆農曆、中文月份週期

聊到將時間從 UTC 轉到台灣時間,居然還是聽到朋友表示使用 +8 小時的做法,驚為天人。這種做法可能會造成後續的問題,例如時區並不會跟著變動,或是遇到日光節約等特殊狀況就容易出事。和西元民國轉換直接 -1911 一樣不穩定。

這篇就用來記錄一下之前看過比較優雅的時區轉換方式,順便將先前存著的時間處理相關資料整理一下,方便之後需要時可以馬上回來查詢。

TimeZoneInfo: 時區資訊

轉換方式主要參考自 [食譜好菜] DateTime 具有文化特性的格式化及時區的轉換在各時區間轉換時間,感謝前人的指引。

關於文化特性,也可以參考本站的 菜雞抓蟲: DateTime.ToString() 之我們不一樣 & CultureInfo 文化特性小筆記 呦。

// 假設現在是要從標準時區 +00:00 轉換到台灣時區,故這邊使用 UtcNow 先取標準世界協調時間
var nowDateTime = DateTime.UtcNow;

nowDateTime.ToString("yyyy/MM/dd H:mm:ss zzz").Dump();
// 2020/08/30 15:56:05 +00:00

// ==================================================

// 傳統的 直接對時間做計算的方式…
var addedDateTime = nowDateTime.AddHours(8);

addedDateTime.ToString("yyyy/MM/dd H:mm:ss zzz").Dump();
// 2020/08/30 23:56:05 +00:00
// 可以看到儘管時間變動了,時區仍然還在 +00:00

// ==================================================

// 使用 TimeZoneInfo 先取得台北時區
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Taipei Standard Time");

// 再使用 TimeZoneInfo 來變更時間
var convertedDateTime = TimeZoneInfo.ConvertTime(nowDateTime, timeZone);

convertedDateTime.ToString("yyyy/MM/dd H:mm:ss zzz").Dump();
// 2020/08/30 23:56:05 +08:00
// 可以看到除了時間變更以外,時區也切換到 +08:00 了!

上面取得台北時區的步驟,可以參照 Time Zone IDs 來查詢想要的時區。這樣的時區切換方式,不僅副作用少,不會因為時區沒轉雷到後續接手的人,也省卻了擔心日光節約等等問題,這種事就交給微軟去煩惱吧!

……

閱讀全文


C#: 字串插值 (String interpolation) 的格式化

自從 C# 有了 字串插值 這東西之後,我就一直是愛用者。畢竟比起 string.format 這東西可是看起來優雅多了。例如:

var message = $"哈囉,{userName} 您的點數將於 {cutoffTime} 到期。";

簡潔又明瞭,一眼就能理解字串內容。實在是挺方便,後來發現這東西還有一些延伸用法,這邊就稍加紀錄一下:

字串插值中能夠做簡易計算,例如:

var message = $"您輸入的數值為:{a}、{b}。他們相加為:{a + b}";

同時,在字串插值時可以針對內容作格式化,只需要用 : 來區隔,妥善運用可以省下一堆 ToString() 的空間。

例如當我們要將時間格式化的時候,就可以:

var date = new DateTime(2020, 8, 9);
var message = $"您的商品已於 {date:yyyy/MM/dd} 抵達。";
// 您的商品已於 2020/08/09 抵達。

另外,數值當然也可以格式化,不過數值的應用比較複雜,主要是用來定下小數點、百分比等符號的位置。 可以參見 自訂數值格式字串 - Microsoft Docs

var cost = 2100;
var message1 = $"您的商品一共是 {cost:#,###} 元";
// 用 # 可以替數字預留位置
// 您的商品一共是 2,100 元

var message2 = $"您的商品一共是 {cost:#,###.00} 元";
// 也可以用 0 來預留位置,若該數字有值就會顯示該數字,沒有就會自動補 0
// 您的商品一共是 2,100.00 元
……

閱讀全文


C#: 使用 System.Environment 取得環境資訊、特殊資料夾路徑

有時候我們會需要取得一些系統資訊,例如說取得設備和當前使用者等資料來寫 Log,或是取得特殊資料夾路徑、讀取環境變數等等。這些時候就可以使用 System.Environment ,這邊就稍微紀錄一下用法。

先列出幾個常用的環境資訊,詳細可查詢的內容可以到 Environment Class 查詢:

資料夾路徑則需要用 Environment.GetFolderPath 搭配 Environment.SpecialFolder 列舉使用,該列舉包含資料夾可以到 Environment.SpecialFolder Enum 查詢。

……

閱讀全文


C#: 程式碼風格備忘

前言:本篇是整理公司規範和網路文章後,方便我自己在各個場所也能回來查閱使用的,故仍會不定時修改(畢竟我這人挺三心二意的)。另外本篇有重新調整過行距,發現有點跑版的朋友可以先 Ctrl+F5 一下,感謝閱讀。

如果你想知道的是如何寫出更優雅、更乾淨、品質更高的程式碼,那並不是該看這篇我個人的備忘錄,我會建議可以閱讀《無暇的程式碼》。或是可以參考這幾篇,我覺得都寫得很好:可不可以不要寫糙 codeClean Code 無瑕的程式碼閱讀筆記易讀程式之美學,共勉之。

如果你是正巧路過並且也寫 C#,希望這篇能讓你做為參考。但請記得,程式碼風格沒有絕對,最終還是回歸到團隊能否接受和將來的可維護性去考慮,畢竟教條是死的,人是活的。了解這樣做背後的原因,以及為自己寫的程式碼負責,這些都比對著隻字片語斤斤計較更加重要。

Nothing is true, everything is permitted. —— Assassin’s creed.

命名原則

想像下一個接手你程式碼的人是個暴力傾向的重度精神病患者

而且他知道你住在哪。  —— 《無瑕的程式碼》

  • 使用有意義的命名,請重視描述性。除了迴圈計數器例外
  • 盡量不要超過五個單字
  • 業界和慣例中有對應縮寫時可以使用縮寫
  • 承上,縮寫兩個字母時全大寫,三個字母以上時只第一字大寫

命名空間

  • 基礎類別庫:{組織} . {大類/應用範圍} . {小類/專案名稱}
    • MyStudio.Libs.Basic
    • MyStudio.Libs.Web.BaseTools
  • 專案類別庫:{專案名稱} . {子專案/類別/用途}
    • MyProject.Permiss.Proxy
    • MyProject.Permiss.Repository
……

閱讀全文


AutoMapper —— 類別轉換超省力

類別間的轉換幾乎是每個專案每個工程師都會碰到的動作,舉凡是分層架構每層之間的轉換,如 Dto 轉換成 ViewModel;或是接收到資料要塞進自定義的類別時也需要進行轉換。但在遠古時代,當我們要把一個類別的資料倒進另一個類別時,總免不了一番折騰

例如一個卡片對戰遊戲的資料庫,光是要先把卡片資料讀取出來就需要:

有些時候也會看見用 Foreach 然後逐一傳值的場景,或是各種差不多的變種情況。同樣的是,光是將一個簡單的卡片資訊轉換成 ViewModel,就花了一大段在做對映的處理。這個過程本身枯燥乏味又占空間,更可怕的是,如果有個陳年資料表,動不動就上百個欄位,那這個轉換過程的恐怖程度可想而知

幸好!天無絕人之路,這種時候就是本日的主角 —— AutoMapper 出場的時候了。

當 AutoMapper 一出手,轉換的過程瞬間就變成:

是不是精簡很多呢?接著就讓我們來看看怎麼開始使用吧!

……

閱讀全文


Electron.net —— 把網頁包成桌面應用吧

因緣際會下想要弄出一些單機小工具來跑,這時候正巧接觸到 Electron.net 這個神器,特別紀錄一下以免忘記。這是 Electron 搭配 .net Core 的框架, Electron 是用 Chromium 和 Node.js 將網頁封裝成桌面應用程式,像是 Visual Studio Code、Slack 也都有使用到 Electron。而 Electron.net 顧名思義就是 .net 用的 Electron 框架囉。

這邊記錄一下自己嘗試時載入套件和建置的流程,主要參考自黑大的 用 ASP.NET Core 寫桌面 GUI 應用程式 - Electron.NETElectron.NET API 快速巡覽 這兩篇文章,以及官方的 API DEMO,特此感謝。

本篇小節:

……

閱讀全文


C#: 位元旗標 (Bit flag) 與列舉

前陣子碰到個資料表儲存方式,因為這種位元運算的方式也常用在權限管理等地方,這邊就順手紀錄一下。

平常遇到二元的情形(例如 開/關、有/沒有),我們會直接宣告個 Boolean 來處理。但這次遇到的是同時有多個「有/沒有」的狀況,但我遇到的程式碼並沒有分成多個 Bool 去做處理,而是直接儲存成一個數值。

由於「有/沒有」只佔據一個位元,那麼將多個狀況按照位元順序排列的話,就只需要一個數字就可以紀錄或傳遞給其他系統了。例如最常見的用處是在權限系統,若有「讀」、「寫」、「執行」等權限,那麼我們按照這個順序去排列,當 讀=可、寫=不可、執行=可 的時候,就記做 101 = 5。這種直接用一組位元表示狀態的方式就叫做位元旗標(Bit flag)

1 讀   = 可
0 寫   = 不可
1 執行 = 可

/* 橫放 */
=> 101 (2進位) 
=> 5 

假使某天老闆靈光一現,決定接下來的新人員工都要記錄他們會的程式語言,並且他們報到的時候就會發一張公司列好的程式語言清單請他們勾選。

Enum & Flags

在 C# 中已經有方便的工具可以處理數字列表,我們可以建立一個叫做 SkillEnum 的列舉(Enum),並且按照上面說明的,將老闆提到的每個技能各自用一個位元來表示。

[Flags]
public enum SkillEnum
{
    C = 1,     // 0001
    PHP = 2,   // 0010
    SQL = 4,   // 0100
    Java = 8,  // 1000
}

註:[Flags]的標籤是指 C# 專門提供給位元旗標使用的 Enum,請參見 FlagsAttribute

只要在 enum 上加上 Flags 的屬性,除了自動按照 2 的次元增加以外,在使用 ToString() 也能更方便看見旗標內容

有了這個列舉之後,我們就可以表達不同排列組合的狀況了。例如:

* C: C
* P: PHP
* S: SQL
* J: Java
===========
J S P C
0 0 0 0 => 什麼都不會
0 0 0 1 => 只會 C
0 0 1 1 => 同時會 C 和 PHP
1 0 1 0 => 同時 PHP 和 Java
1 1 1 1 => 全部都會
……

閱讀全文


EPPlus —— 輕鬆處理 Excel

前陣子工作需要匯出一些資料表,因此用到了 EPPlus 這套工具來把資料匯出成 Excel。由於這需求似乎會挺常遇到的,決定記一下。

目標:稍微紀錄一下這次碰到 EPPlus 的用法。

EPPlus 是在 .NET Framework 或 .NET Core 上提供控制 Excel 的元件,操作簡單好懂,當有需要在網頁上讓人將表格資料下載成 Excel 的功能時就可以試著使用。常常一併被提起的還有另一個一樣老牌的相似功能元件 NPOI,不過我個人只用過 EPPlus 便不再贅述。關於更詳細的介紹,可以參閱黑暗執行緒的這篇 比 NPOI 更討喜的 Excel 元件 - EPPlus!,儘管是有些久遠的文章但仍能迅速了解 EEplus 的賣點和差異。

我在使用 EPPlus 時主要的參考來自於 EPPlus 的 Wiki,每個功能都有說明及範例,同時也有範例專案可以下載,寫得相當詳細。另外還找了如 導出 Excel 之 Epplus 使用教程 - Wico’s Blog使用 EPPLUS 操控 Excel - 碼農的學習日誌 這些有逐步說明的文章,在此感謝。

……

閱讀全文


Asp.net MVC: 連線資料庫、簡單實作 CRUD

在教學時直接使用 EF 對資料庫跑繫結的方式產生各頁面,但得到了「點一點東西就跑出來了搞不懂呀」的回饋,心想有道理。因此從頭開始實作一遍,並記錄下來。(雖然做完還是覺得,直接用 EF 跑的話果然比較安全方便啊)

目標:實作一個 MVC 架構,具資料庫基本操作功能的網站,其中包含連線至資料庫的 model、對其進行調用的 controller 以及顯示的 view。

註:本文預設已在本地電腦上安裝了 SQL Server,並且建立了測試用的資料庫 Test 及表 card,詳情會在文章內述。另外,由於在寫這邊的時候是為了練習手動從編碼開始嘗試連線,故將不使用 EF 連線產生 Edmx 的方式,而是直接手工編寫程式碼進行操作。

另外,關於直接從資料表自動產生可操作的頁面,亦即使用 Entity Framework 做資料繫結的方式,請見 Asp.net MVC 筆記:Entity Framework 連線資料庫

……

閱讀全文