CryptoStream的成員方法確實有些混亂,細細研究一下,其實也不是特別混亂,也算符合.NET中的某些命名規則吧。
先說Flush相關的,感覺這個更重要些。
首先從Stream類繼承來的Flush方法並沒有執行流的Flush操作,CryptoStream改寫基類的Flush方法為空白:
而CryptoStream自己的FlushFinalBlock才進行所謂的Flush操作(難道微軟想用這種方式提醒開發人員CryptoStream的Flush操作很重要嗎?),這個操作會將內部緩衝區的資料進行寫入並清空緩衝區,注意由於CryptoStream會包含安全敏感資訊,因此應該儘快清空緩衝區。(同Stream一樣,結束CryptoStream也會調用FlushFinalBlock,後面會詳細講結束CryptoStream的操作)。
通過代碼也可以驗證:
//+ using System.IO;
//+ using System.Security.Cryptography;
using(var aes = Aes.Create())
using(var ms = new MemoryStream())
using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.WriteByte(1);
Console.WriteLine(ms.Length);
ms.Flush();
Console.WriteLine(ms.Length);
cs.FlushFinalBlock();
Console.WriteLine(ms.Length);
}
上面代碼在我的電腦(.NET 4.0)會輸出:
0
0
16
只有調用FlushFinalBlock後,資料才被真正寫入,而Stream.Flush方法是無效的!
接著看看CryptoStream的資源清理的方法:
class CryptoStream
//Stream繼承IDisposable
//調用FlushFinalBlock(),並且調用內部Stream的Close()
protected void Dispose();
//繼承自Stream類,調用Dispose(protected)
public void Close();
//調用Close()
public void Clear();
//調用Close()
public void Dispose();
其實CryptoStream的Dispose, Clear, Close都是執行同一個操作。那麼為什麼弄這麼多方法呢?這個可能跟.NET的內建類庫命名有些關係。首先CryptoStream繼承自Stream,後者繼承IDisposable介面,自然得有Dispose方法。接著Stream類相關的類(比如FileStream,StreamReader……)都有Close方法,等價於Dispose方法的。最後.NET安全中密碼學相關的類都有Clear方法,也是等效於Dispose的。而CryptoStream既屬於Stream類又屬於密碼學類型,所以這麼多Dispose方法的等價方法也不足為怪。
在ILSpy中查詢Clear方法,可以看到許多System.Security.Cryptography的類型都有這個方法。(一般都繼承IDisposable)