使用C#加密文本时,我遇到了一个奇怪的问题。ReSharper(我同意)建议替换此代码上的using
块:
public object GetEncryptedOrDefault(object value, ICryptoTransform encryptor)
{
if (encryptor is null)
{
throw new ArgumentNullException(nameof(encryptor));
}
var isEncryptionNeeded = value != null;
if (isEncryptionNeeded)
{
using var memoryStream = new MemoryStream();
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
using var writer = new StreamWriter(cryptoStream);
var valueAsText = value.ToString();
writer.Write(valueAsText);
}
var encryptedData = memoryStream.ToArray();
var encryptedText = Convert.ToBase64String(encryptedData);
return encryptedText;
}
return default;
}
对此简化的代码(注意使用声明而不是块):
public object GetEncryptedOrDefault(object value, ICryptoTransform encryptor)
{
if (encryptor is null)
{
throw new ArgumentNullException(nameof(encryptor));
}
var isEncryptionNeeded = value != null;
if (isEncryptionNeeded)
{
using var memoryStream = new MemoryStream();
using var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
using var writer = new StreamWriter(cryptoStream);
var valueAsText = value.ToString();
writer.Write(valueAsText);
var encryptedData = memoryStream.ToArray();
var encryptedText = Convert.ToBase64String(encryptedData);
return encryptedText;
}
return default;
}
嗯..第一个效果很好,并且能够加密文本。但是第二个不起作用! encryptedData
为空,因此会产生一个空的encryptedText
。
我看不到问题。为什么?
由于writer
的作用域不再局限于cryptoStream
的using块,因此现在就在从函数返回之前将其处置(而不是在cryptoStream
的作用域结束时处置)。但是它没有将其内容刷新到流中,因为您没有在其上调用Flush
,并且其AutoFlush
属性默认为false
。
public object GetEncryptedOrDefault(object value, ICryptoTransform encryptor)
{
if (encryptor is null)
{
throw new ArgumentNullException(nameof(encryptor));
}
var isEncryptionNeeded = value != null;
if (isEncryptionNeeded)
{
using var memoryStream = new MemoryStream();
using var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
using var writer = new StreamWriter(cryptoStream);
var valueAsText = value.ToString();
writer.Write(valueAsText);
writer.Flush();
var encryptedData = memoryStream.ToArray();
var encryptedText = Convert.ToBase64String(encryptedData);
return encryptedText;
}
return default;
}
在您的第一个示例中,writer
在用完要写入的流之前已被处置(因此冲刷其缓冲区),因此在尝试访问它时该流不会为空。