今天遇到一個以前從未遇到過的小問題。我想把一個類別的建構式做成多載型式, 卻突然發現這個看起來很小的問題, 似乎並沒有直覺的做法
2014/12/14
2014/11/6
[入門] .Net 非同步處理與同步機制全解析 (三)
.Net 4.5 新增的 Async/Await 功能也出來一陣子了, 我相信有許多人都已經對它相當熟悉。不過我在本文中要把重點往回拉一點點, 談一下 .Net 中早已提供的非同步功能。坦白說, 這才是我一開始想寫的東西。
在「[入門] .Net 非同步處理與同步機制全解析 (一)」一文中, 我們已經看過以手動方式叫出執行緒以進行非同步作業的方法。在這裡, 我要介紹以委派方式以進行非同步作業的方法
2014/10/29
當隨機不再隨機的時候
前幾天, 我寫了一個 Unit Test, 用來測試一個非同步的資料庫寫入方法。如果我一次寫入一百筆, 那麼結果很順利; 寫入兩百筆, 也很順利; 一路測到一千筆, 都很順利, 都能夠在一秒之內成功結束。直到測到一千一百筆, 突然這個 Unit Test 執行不完了。我看到測試總管中狀態條不停地跑, 完全沒有停止的跡象, 直到我把測試取消為止
2014/10/23
解決 .Net 日期與 SQL 日期的匹配問題
雖然這是一個陳年的老問題, 我在實際應用中卻從來沒有給我帶來麻煩 -- 直到今天。當然, 這也是一個陷阱; 如果我不是以前就知道有這個問題, 我恐怕會百思不得其解。
這個問題很簡單, 相信許多人都有經驗: 把一個日期欄位寫進資料庫, 再取出來時, 發現兩個日期並不相等。它的陷阱在於, 這兩個日期可能有完全相同的年、月、日、時、分、秒, 但是寫進去 SQL 之後, 再讀出來, 它的 millisecond 值卻不同。Ticks 也不同。這個問題使得我的單元測試始終過不了
2014/4/28
[入門] T4 入門教學
T4 是從 Visual Studio 2008 之後加入的新功能, 目的是提供一個文字範本, 讓開發者以動態方式產生文字內容, 例如程式碼。或許你會覺得 "T4" 這個名字很奇怪, 但事實上它是 "Text Template Transformation Toolkit" 縮寫。因為它的開頭字母剛好是四個 T, 所以就稱為 T4。
Visual Studio 本身大量地使用 T4 作為動態程式碼的輸出工具。當然, 我們也可以使用 T4 來產生我們自己的程式碼。不過, 我們不僅可以產生程式碼, 基本上, 我們可以使用它來產生各種文字
2014/4/21
[WinForm] 如何在 WinForm 應用程式中開啟 Console 視窗
時常寫 Windows Form 程式的朋友一定知道, 我們在 Windows Form 程式中一樣可以使用 Console.Write() 方法。這些訊息可以在 Visual Studio 中的「輸出視窗」裡看見。然而, Visual Studio 本身就有許多訊息顯示在輸出視窗裡, 所以我們時常有可能漏掉某些訊息沒看到, 或者需要不停地往回捲動, 才能找到。此外, 如果你希望這些訊息是能夠讓使用者看到的, 該怎麼辦?
2014/4/2
[入門] .Net 非同步處理與同步機制全解析 (二)
這一篇入門教學距離上一篇([入門] .Net 非同步處理與同步機制全解析 (一))已經有足足三年多的時間。之所以延宕那麼久, 主要是因為微軟已經開始提供平行處理及非同步機制的功能更新; 許多功能及用法不停地出現, 連我自己都搞不清楚, 所以我也沒辦法繼續著手這一系列文章。
直到 .Net Framework 4.5 開始, 我覺得應該可以算是一個適當時機, 可以繼續來寫這個系列文章了
2013/12/27
在 Console 程式中讓文字保持在同一行顯示
我們都知道我們可以在 Console 程式中以 Console.WriteLine 和 Console.Write 輸出文字到一個命令視窗裡。但是不管是 Write 或者 WriteLine 方法, 文字的走向都是向右、向下的, 從來不會回頭。因此, 如果你的輸出文字太多, 就會需要捲頁; 如果超過差不多12頁以後, 它只會保留12頁(大約是288行左右, 根據預設值), 更上方的文字通通會被截掉, 再也看不見了。
有沒有辦法讓我們既看到輸出結果, 又能讓這些輸出的文字不要佔據那麼多空間呢?
2013/12/2
[ASP.NET] 在 App_Code 下存取外部 Assembly
App_Code 是一個 ASP.NET 網站專案的特殊子目錄。如果你的專案不是 Web Site 專案而是 Web Application 專案, 你並不需要、也不應該特別建立一個 App_Code 子目錄來存放你的程式碼 -- 除非是為了某種特殊的目的
2013/11/12
台灣三碼郵遞區號對應程式庫
不知道是否我的查詢功力太差, 或者真的沒有人願意提供, 我在網路上找了老半天, 就是找不到一個可用的現成程式。那些現成的程式, 如果不是非 C# 語言, 就是欲言又止... 說真的, 這東西一點都不難, 只差要不要把資料打上去而已。
既然找不到, 就自己寫吧!
2013/9/5
.Net 程式內註解的幾個小細節
最近在編寫程式時, 注意到幾個關於程式註解的注意事項, 我把它記錄起來, 同時提供朋友們參考。
註解內要怎麼斷行? 例如以下用來註解 interface 的程式行, 你在註解中把它斷行是無效的:
2013/6/30
ASP.NET 和 VS 2013 新功能彙整
微軟在近日 (2013/6/26) 公開了最新的 Visual Studio 2013 Preview (預覽) 版本; 我在前幾天的發文中也有提到過。不過, 到底這個最新版本有什麼不一樣之處? 微軟又為什麼在短短一年之後, 再度推出 Visual Studio 的新版本? 由於現在的資訊都不充份, 我想, 唯一, 也是最好的答案, 恐怕也只有 Scott Hanselman (現任微軟 Azure & Web Tools 的 Principal Community Architect 兼書籍作者) 能夠回答你了! 有興趣的朋友可以參考由他主講的 What's New in ASP.NET and Visual Studio 2013 這段影片
2011/11/26
.NET Framework 新風貌
就目前所知, 下一版的 .NET Frameworks (根據目前消息,版號應該是 4.5) 應該沒有什麼驚天動地的變革, 預計上市日期也還沒有確定。不過隨著今年 (2011) 在 BUILD 大會上公布的 VS2011 Developer Preview Version (簡稱 "vNext") 讓大家可以廣泛試用, 我們逐漸了解這個新版本的大致狀況。
2011/2/8
.Net 集合型別的效率探討
我要在這裡說明的所謂「集合型別」指的並不是泛指 System.Collections 命名空間下的各種型別, 而是特別指自從 .Net 3.5 之後才出現的 Sets (集合) 型別, 特別是 System.Collections.Generic.HashSet 與 System.Collections.Generic.SortedSet 這兩個實作 ISet 介面的類別。ISet 介面是專門針對集合作業而設計的, 它提供了幾個特別的方法:
2010/12/18
[入門] .Net 非同步處理與同步機制全解析 (一)
不管你學的是何種程式語言, 非同步及平行處理總是最令人費解的部份之一。如果你沒有過人的邏輯觀念, 那麼要把非同步程式寫好, 恐怕有一定的困難度。不過最難的部份不在技術上, 而是到底在何種場合下可以採用非同步或平行處理。在日常生活中, 我們採用的邏輯大多是循序進行的, 也就是說, 等到前一件事情完成之後, 才去進行下一件。但是在某些情況下, 非同步處理是比較合乎情理的做法。
2010/9/8
[Regex] 值得注意的 Regular Expression 樣式的潛在風險
Regex 本身已經十分複雜, 但不知道大家有沒有想過, 它的解析引擎和處理機制又是如何實作的呢? 一般來講, Regular Expression 的解析引擎可以分為三種, 一種叫做 DFA (Deterministic Finite Automation, 決定性有限自動機制), 另一種叫做 NFA (Nondeterministic Finite Automation, 非決定性有限自動機制), 還有一種叫做 POSIX NFA。.Net 採用了傳統的 NFA 引擎, 使得它既能兼顧速度與功能, 但缺點就是由於傳統 NFA 只接受它找到的第一個相符比對,它也可能讓其它比對無法被找到 (POSIX NFA 雖然可以找到, 但速度緩慢)
2010/4/23
[入門] .NET 自訂型別
我可以理解為什麼我老婆開了十年的同樣一部車, 都不知道原來在 N 檔和 D 檔之間切換可以不必去按那個安全鈕; 但是我卻無法理解為什麼有一個已經寫了好幾年 .NET 程式的人, 在這輩子中竟然沒有寫過任何一個自訂型別。對這件事, 我唯一想得到的解釋, 就是從來沒有人跟他說過自訂型別的好用之處。
所以, 這件事也讓我決心把自訂型別特別整理成一個主題。雖然我在本文中會用到一些進階技巧, 對真正的初學者而言恐怕有點吃力, 但是這畢竟是 .NET 中很基礎、很一般的常識, 所以我還是把它歸類到「入門文章」裡面
2010/3/2
[Regex] 進階群組建構
Regular Expression (規則運算式, 以下簡稱為 Regex) 實在不是一個易懂的課題; 但是, 如果我們要在一大堆文字裡面挑出部份具有特定規則的隻字片語, Regex 恐怕是我們唯一能用得上的工具
2010/1/25
[SQL] 使用 Stored Procedure 動態組成 SQL 查詢指令
以下示範一個可以動態組成查詢子句的 SQL 指令, 以 MS SQL 的 Stored Procedure 寫成。其中, 如果任一個參數(或全部)傳入 NULL 值, 即代表不限制那個欄位的條件。
2010/1/20
善用擴充方法
雖然我個人認為自從 .Net 2.0 以後引進的 Lambda 運算式在某種程度上破壞了 C# 的嚴謹度, 但是對於一個程式設計師而言, 我們也不能否定它對於程式撰寫所能提供的方便性。擴充方法 (Extension Method) 也是一樣; 如果你還不知道擴充方法是什麼, 那麼當你看完本文之後, 我相信你會感謝微軟提供了這麼好用的功能。
擴充方法是 .Net 3.5 才提供的, 所以在之前的版本中並沒有這東西。它的實作很簡單 (相對於其功能), 絕對超乎所有人的想像。請先看看以下的程式碼:
public static class cls
{
public static string keep10chars(this string str)
{
return (str.Length > 10) ? str.Substring(0, 10) : str;
}
}
撰寫擴充方法就是這麼簡單而已, 以下幾個重點要記住:
- 它必須包在一個宣告為 public static 的類別裡面 (如上例中的 public static class cls); 類別名稱可以隨便取, 並不影響執行及引用。
- 方法必須以 public static [type] 宣告 (如上例中的 public static string)。
- 方法不能沒有參數, 而且其型別必須以 this [type] 宣告 (如上例中的 this string)。
如果你寫在網頁裡, 那麼完整的網頁程式如下:
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Write("12345678901234567890".keep10chars());
}
}public static class cls
{
public static string keep10chars(this string str)
{
return (str.Length > 10) ? str.Substring(0, 10) : str;
}
}
如上例, 當你把這個擴充方法 keep10chars 寫好之後, 你的字串物件就自動多了一個 .keep10chars() 方法可以使用了。在這個例子中, "12345678901234567890".keep10chars() 的輸出是 "1234567890"。意思就是說, 你已經為 string 型別建立了一個擴充方法 keep10chars(), 可以隨時引用。
擴充方法的用法就是這麼簡單。你不需要另外建立一個繼承自 string 的新型別, 而是直接套用在現有的系統型別上面; 也沒有什麼繁瑣的宣告或語法。你說, 這是不是非常方便呢?
擴充方法對於 ASP.NET 程式而言, 還有另一個極為友善的功能, 那就是它可以毫無問題的用在繫結控制項的 tag 裡面。舉個例子, 假設你的 GridView 中有一個 TemplateField, 你可以把擴充方法直接運用在從 Eval 函式撈出來的資料上:
<asp:TemplateField HeaderText="OperatorName" SortExpression="OperatorName">
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("OperatorName") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Eval("OperatorName").ToString().keep10chars() %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
運用擴充方法, 我們就可以對所繫結的資料進行後處理, 而且是用非常簡單而輕鬆的做法。
不過, 請注意, 我發現我在 .Net 4.5 上建立的 ASP.NET 專案上建立的擴充方法, 總是發生未定義的錯誤。這個網頁有套用 Master Page, 我不知道這是否是引發錯誤的原因; 不過解法很簡單。
我的擴充方法是這樣定的:
namespace Johnny
{
public static class abc
{
public static string Gender(this string isMale)
{
return (1)? "男" : "女";
}
}
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
...
換句話說, 這個擴充方法 Gender() 是定義在和網頁相同的命名空間之下的。但是, 我還是必須以手動方式在網頁上加上明確的 IMPORT 指示詞, 這個擴充方法才能被找到:
<%@ Page Title="" Language="C#" MasterPageFile="~/..." %>
<%@ Import Namespace="Johnny" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<h2>...
...
<asp:TemplateField ...>
<ItemTemplate>
<asp:Label ID="lbIsMale" runat="server" Text='<%# Eval("IsMale").Gender() %>' />
</ItemTemplate>
</asp:TemplateField>
我不知道為什麼這種問題會發生, 我只知道加上 IMPORT 指示詞就能解決這個問題。