Time of Update: 2018-12-07
在前一篇文章:.NET(C#):RSA的SignHash和VerifyHash,我講到使用RSA的SignHash和VerifyHash可以同樣做到SignData和VerifyData,事實上還有一種方法進行公開金鑰加密的簽名認證。就是.NET中的AsymmetricSignatureFormatter和AsymmetricSignatureDeformatter。直接翻譯就是“不對稱式加密簽名格式化器和反格式化器”。分明用來進行建立簽名和驗證簽名的。 他們都需要操作一個不對稱式加密類型(即公
Time of Update: 2018-12-07
FormatterService(在System.Runtime.Serialization命名空間內)的GetUninitializedObject方法是.NET還原序列化中CLR初始化對象用到的方法(眾所周知,還原序列化中對象的建構函式是不被調用的)。這個方法我們也可以直接使用來達到相同的效果。 如下代碼:using System;using System.Runtime.Serialization; namespace Mgen{ class a {
Time of Update: 2018-12-07
電腦中資料大小一般以位元組為單位,資料類型通常是long類型,轉換成易讀的單位字串,比如1024位元組就顯示1KB。1024*1024位元組則顯示1MB…… Google中搜尋了半天,在StackOverflow中找到一個好的答案:http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java 不過是用Java寫的,把他改成C#:public
Time of Update: 2018-12-07
注意:C/C++的輸出可能在不同編譯器下會有不同結果。如果你的編譯器和我的不一樣,建議複製C/C++代碼並在自己的編譯器上運行下看結果。 下面所有C#代碼由Visual C# 2010 Express編譯運行下面所有C/C++代碼由Visual C++ 2010 Express編譯運行 C++的浮點輸出:預設保留6位有效數字代碼:double arr[4] = { 123.4567, 12345670, 12.34567, 0.001234567 }; for(int i = 0; i <
Time of Update: 2018-12-07
訣竅就在CompareOptions.IgnoreWidth枚舉。這個枚舉可以在CompareInfo.Compare方法中用到。而CompareInfo對象可以在CultureInfo的CompareInfo屬性中得到。 代碼://半形(英文)abc78var a = "abc78";//全形的abc78var b = "abc78"; Console.WriteLine(String.Compare(a,
Time of Update: 2018-12-07
C#中ref和out的文章有很多,這篇文章主要從IL上分析out參數的本質。 目錄out = ref + ParameterAttributes.Out 反射調用ref和out方法 Emit構建out或ref參數 返回目錄 out = ref + ParameterAttributes.Out看兩個out和ref的方法。static void test_ref(ref int i){ } static void test_out(out int i){ i = default(int); }
Time of Update: 2018-12-07
比如這樣一個類,我們用XmlArrayItem特性標明數組內出現的元素類型:public class a{ [XmlArrayItem(Type = typeof(int)), XmlArrayItem(Type = typeof(Guid)), XmlArrayItem(Type = typeof(string))] public object[] arr = new object[] { 12, "hehe", Guid.NewGuid() };} 序列化的XML是:<a
Time of Update: 2018-12-07
首先如果您看下面代碼有些費解的話,推薦先閱讀以下MSDN上關於平台叫用的指定字元集文章:http://msdn.microsoft.com/zh-cn/library/7b93s42f.aspx 學習.NET(C#)的平台叫用和對象封送,你會發現其實同樣的系統API函數的平台叫用定義可以有多種形式的,本文就拿WinAPI的MessageBox開涮。首先通過DllImportAttribute.CharSet來自動指定名稱探索(根據DllImportAttribute.ExactSpelling)
Time of Update: 2018-12-07
假設有這麼一個簡單的ConfigurationSection類型(只有一個Id屬性):class MySection : ConfigurationSection{ [ConfigurationProperty("id")] public int Id { get { return (int)this["id"]; } set { this["id"] = value; } } } 那麼你的設定檔只能這樣寫:<configuration&
Time of Update: 2018-12-07
MSDN的這篇文章有點講地不清楚:http://msdn.microsoft.com/en-us/library/s9ts558h.aspx 文中說的字串的COM調用預設封送形式是UnmanagedType.Bstr,而平台叫用的預設封送形式是UnmanagedType.LPTStr。這個LPTStr是和平台相關的,就是WinAPI中的TCHAR定義(98/Me是ANSI,NT/2000/XP/…是Unicode)。然後這一段落就結束了……是的,MSDN上面的這些說的都沒錯,但是它應該提一下平台
Time of Update: 2018-12-07
其實.NET中的訊號量(Semaphore)是作業系統維持的一個整數。當整數位0時。其他線程無法進入。當整數大於0時,線程可以進入。每當一個線程進入,整數-1,線程退出後整數+1。整數不能超過訊號量的最大請求數。訊號量在初始化的時候可以指定這個整數的初始值。 System.Threading.Semaphore類的建構函式的兩個參數第一個就是訊號量的內部整數初始值,也就是初始請求數,第二個參數就是最大請求數。如果沒有額外操作訊號量的話,訊號量的運行限制就取決於這個初始請求數,比如下面代碼://+
Time of Update: 2018-12-07
我們知道,AppDomain.ProcessExit能監視當前進程的退出,而Process.Exited事件只能監視其他進程的退出。而且如果進程被強制結束AppDomain.ProcessExit不會發生的。綜上事實,我們可以用兩個進程互相監視另一個進程的Process.Exited事件來,然後如果一個進程被結束,另一個進程會重新開啟這個程式。 比如樣本中兩個程式,mgen_p1,和mgen_p2。一個程式結束後,另一個程式會馬上重新運行被結束的程式。當然如果兩個程式同時被結束,那麼他們會被徹底
Time of Update: 2018-12-07
一個動態對象竟然支援自己調用自己,根據MSDN的解釋,此項功能僅在C#中被支援,VB並不可以。具體過程則是改寫動態對象(DynamicObject類)的TryInvoke方法。和普通函數調用的TryInvokeMember方法類似。TryInvoke的第一個參數是Binder:InvokeBinder。但是和TryInvokeMember的InvokeMemberBinder不一樣,它沒有Name屬性,因為對象自己調用自己自然沒有方法名稱。其他屬性不需要多說明,CallInfo代表調用資訊。Re
Time of Update: 2018-12-07
HTTP請求包頭資訊中有一個Range屬性可以指定索取部分HTTP請求的檔案。在.NET中則通過HttpWebRequest.AddRange方法來定義資料的範圍。當添加了Range屬性的HTTP請求發送後,如果伺服器支援該請求,也就是說支援部分資料提取(也是我們常說到的支援斷點續傳的下載,所謂斷點續傳的下載就是用一個Range屬性來指定沒有下載到的範圍),那麼伺服器會返回Partial Content狀態值。否則會返回OK狀態值(200代碼)。注意如果伺服器支援Range但是HTTP
Time of Update: 2018-12-07
今天遇到一個問題,需要從根據一個檔案嘗試擷取其文本編碼。不是很難呵呵,無非就是根據前幾個位元組判斷字元順序標記(BOM),如果檔案不包含BOM的話,返回一個預設值。 代碼:/// <summary>/// 根據檔案嘗試返回字元編碼/// </summary>/// <param name="file">檔案路徑</param>/// <param name="defEnc">沒有BOM返回的預設編碼</param>/// &
Time of Update: 2018-12-07
PLINQ的運行結果是無序的,也就是不保持原來集合的順序來操作(當然除了一些專門的排序操作)。原因則是線程的並發執行本來就充滿了不確定性,把原來一個任務分割成好幾個部分同時進行返回的結果會打亂原來的順序,如果要強制保留順序,肯定要浪費一些效能,PLINQ是可以這樣的,但預設不這樣。 先看一個LINQ樣本:var arr = new int[] { 1, 2, 3, 4, 5 };var res = arr.Where(i => i != 3);結果是:1, 2, 4,
Time of Update: 2018-12-07
和for/foreach中發生異常的表現一樣,Parallel迴圈中的任何異常都會使整個迴圈終止,注意由於整個迴圈是分塊同時進行的,因此整個迴圈不會立即終止(如果有一個線程進行中長時間工作的話,而且是發生在CancellationToken的ThrowIfCancellationRequested方法之後)。 代碼:try{ Parallel.For(0, 5, (i) => { throw new Exception("異常。迭代數字:" + i); })
Time of Update: 2018-12-07
更新:在C# 5.0後,await所產生的取消Task異常會直街拋出異常。比如下面的代碼,在C# 5.0/.NET 4.5中等效於:var src = new CancellationTokenSource();src.CancelAfter(100);try{ await Task.Factory.StartNew(() => { Thread.Sleep(1000); src.Token.ThrowIfCancellationRequested(
Time of Update: 2018-12-07
當你在一個Task執行中拋出異常,比如:Task.Factory.StartNew(() =>{ throw new Exception();});運行該方法,沒有任何異常拋出。 事實上此時Task的異常處於未覺察狀態,這個未覺察狀態的異常會在記憶體回收時終結器執行線程中被拋出。為了誘發這個異常,我們可以通過GC.Collect來強制記憶體回收從而引發終結器處理線程,此時Task的未覺察異常會被拋出。//在Task中拋出異常Task.Factory.StartNew(() =>
Time of Update: 2018-12-07
這個特性太碉堡了,很像WPF中的資料繫結,當然本質就是Visual Studio在調試時利用反射擷取對象的值。 建構函式中的屬性值(就是{}中的內容)不僅僅可以是簡單的屬性值。還可以是索引器,而且這一切可以嵌套。(DebuggerDisplay特性(DebuggerDisplayAttribute類型)在System.Diagnostics命名空間內) 來定義一個有DebuggerDisplay的類: