[英]Object 'iCrypt' can be disposed more than once
我已经看到有关此问题的几个问题。 例如:
但是我不能完全确定我应该如何处理我的代码。 我从代码分析中得到的警告是:
1> D:\\ My Programs \\ 2017 \\ PTSTools \\ PTSTools \\ PTSTools.cs(81):警告CA2202:Microsoft。用法:对象'iCrypt'可以在方法'PTSToolsClass.Crypt(string,string,bool )”。 为避免生成System.ObjectDisposedException,不应在一个对象上调用Dispose多次。:行:81
有问题的方法:
private string Crypt(string strData, string strPassword, bool bEncrypt)
{
byte[] u8Salt = new byte[] { ... };
PasswordDeriveBytes iPass = new PasswordDeriveBytes(strPassword, u8Salt);
Rijndael iAlg = Rijndael.Create();
iAlg.Key = iPass.GetBytes(32);
iAlg.IV = iPass.GetBytes(16);
ICryptoTransform iTrans = (bEncrypt) ? iAlg.CreateEncryptor() : iAlg.CreateDecryptor();
MemoryStream iMem = new MemoryStream();
CryptoStream iCrypt = new CryptoStream(iMem, iTrans, CryptoStreamMode.Write);
byte[] u8Data;
if (bEncrypt)
u8Data = Encoding.Unicode.GetBytes(strData);
else
u8Data = Convert.FromBase64String(strData);
try
{
iCrypt.Write(u8Data, 0, u8Data.Length);
iCrypt.Close();
if (bEncrypt)
return Convert.ToBase64String(iMem.ToArray());
else
return Encoding.Unicode.GetString(iMem.ToArray());
}
catch
{
return null;
}
finally
{
iCrypt.Close();
}
}
有人可以解释一下为什么我在finally
的代码行中收到此警告吗?
谢谢。
更新:
根据评论,我将其更改为:
private string Crypt(string strData, string strPassword, bool bEncrypt)
{
byte[] u8Salt = new byte[] { ... };
PasswordDeriveBytes iPass = new PasswordDeriveBytes(strPassword, u8Salt);
Rijndael iAlg = Rijndael.Create();
iAlg.Key = iPass.GetBytes(32);
iAlg.IV = iPass.GetBytes(16);
ICryptoTransform iTrans = (bEncrypt) ? iAlg.CreateEncryptor() : iAlg.CreateDecryptor();
MemoryStream iMem = new MemoryStream();
using (CryptoStream iCrypt = new CryptoStream(iMem, iTrans, CryptoStreamMode.Write))
{
byte[] u8Data;
if (bEncrypt)
u8Data = Encoding.Unicode.GetBytes(strData);
else
u8Data = Convert.FromBase64String(strData);
try
{
iCrypt.Write(u8Data, 0, u8Data.Length);
iCrypt.Close();
if (bEncrypt)
return Convert.ToBase64String(iMem.ToArray());
else
return Encoding.Unicode.GetString(iMem.ToArray());
}
catch
{
return null;
}
}
}
但是我现在有这些警告:
1>D:\My Programs\2017\PTSTools\PTSTools\PTSTools.cs(77): warning CA2202: Microsoft.Usage : Object 'iCrypt' can be disposed more than once in method 'PTSToolsClass.Crypt(string, string, bool)'. To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object.: Lines: 77
1>D:\My Programs\2017\PTSTools\PTSTools\PTSTools.cs(77): warning CA2202: Microsoft.Usage : Object 'iMem' can be disposed more than once in method 'PTSToolsClass.Crypt(string, string, bool)'. To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object.: Lines: 77
现在,它不喜欢catch块。
更新:
了解:
private string Crypt(string strData, string strPassword, bool bEncrypt)
{
byte[] u8Salt = new byte[] { 0x26, 0x19, 0x81, 0x4E, 0xA0, 0x6D, 0x95, 0x34, 0x26, 0x75, 0x64, 0x05, 0xF6 };
PasswordDeriveBytes iPass = new PasswordDeriveBytes(strPassword, u8Salt);
Rijndael iAlg = Rijndael.Create();
iAlg.Key = iPass.GetBytes(32);
iAlg.IV = iPass.GetBytes(16);
ICryptoTransform iTrans = (bEncrypt) ? iAlg.CreateEncryptor() : iAlg.CreateDecryptor();
MemoryStream iMem = new MemoryStream();
using (CryptoStream iCrypt = new CryptoStream(iMem, iTrans, CryptoStreamMode.Write))
{
byte[] u8Data;
if (bEncrypt)
u8Data = Encoding.Unicode.GetBytes(strData);
else
u8Data = Convert.FromBase64String(strData);
try
{
iCrypt.Write(u8Data, 0, u8Data.Length);
if (bEncrypt)
return Convert.ToBase64String(iMem.ToArray());
else
return Encoding.Unicode.GetString(iMem.ToArray());
}
catch
{
return null;
}
}
}
因为finally
一个的块try-(catch-)finally
块总是执行 ,分析器看到此:
try
{
iCrypt.Close();
}
finally
{
iCrypt.Close();
}
然后,它正确地推断出这些调用可以连续发生,从而导致ObjectDisposedException
抛出在第二个调用中。
因此:您无需在try
块中使用iCrypt.Close()
,因为无论是否发生异常,它将始终在finally
关闭。
您正在调用iCrypt.Close(); 两次,从try语句中删除该调用,就可以了。
来自代码分析的消息很清楚。 您的代码两次处置(关闭)iCrypt。 在try块中一次,在finally块中一次。 删除行iCrypt.Close();
在try块中(在iCrypt.Write(...)
和if(...)
,警告将消失。
更好的办法是使用块:
using (CryptoStream iCrypt = new CryptoStream(...)) {
.... // your code without the finally block
}
无论是否在块内引发异常,使用方法都将调用iCrypt.Close()。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.