我有一个实现IDisposable接口的类。我正在使用webclient使用AsyncDownloadString下载一些数据。
我想知道我是否在构造函数中和Web客户端的using语句中正确声明了我的事件处理程序?这是在Dispose方法中删除事件处理程序的正确方法吗?
否决这是使用IDisposable接口的正确方法吗?
public class Balance : IDisposable
{
//Constructor
WebClient wc;
public Balance()
{
using (wc = new WebClient())
{
//Create event handler for the progress changed and download completed events
wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
}
}
~Balance()
{
this.Dispose(false);
}
//Get the current balance for the user that is logged in.
//If the balance returned from the server is NULL display error to the user.
//Null could occur if the DB has been stopped or the server is down.
public void GetBalance(string sipUsername)
{
//Remove the underscore ( _ ) from the username, as this is not needed to get the balance.
sipUsername = sipUsername.Remove(0, 1);
string strURL =
string.Format("https://www.xxxxxxx.com",
sipUsername);
//Download only when the webclient is not busy.
if (!wc.IsBusy)
{
// Download the current balance.
wc.DownloadStringAsync(new Uri(strURL));
}
else
{
Console.Write("Busy please try again");
}
}
//return and display the balance after the download has fully completed
void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
//Pass the result to the event handler
}
//Dispose of the balance object
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
//Remove the event handlers
private bool isDisposed = false;
private void Dispose(bool disposing)
{
if (!this.isDisposed)
{
if (disposing)
{
wc.DownloadProgressChanged -= new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
wc.DownloadStringCompleted -= new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
wc.Dispose();
}
isDisposed = true;
}
}
}
答案 0 :(得分:8)
使用IDisposable对象有两种正确的方法:
using
区块中
或强> using
块创建新类的所有实例。请注意,我说“或”,而不是“和”。做一个或另一个,但不是两个。
在这里,当您在构造函数中使用using
块创建WebClient实例时,在有机会在其他任何地方使用它之前将其处置掉。在这种情况下,您应该只选择选项二。
答案 1 :(得分:7)
除了wc
被处理两次以外GetBalance
处置完毕后wc
将永远使用public class Balance : IDisposable
{
//Constructor
WebClient wc;
public Balance()
{
wc = new WebClient();
//Create event handler for the progress changed and download completed events
try {
wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
} catch {
wc.Dispose();
throw;
}
}
~Balance()
{
this.Dispose(false);
}
//Get the current balance for the user that is logged in.
//If the balance returned from the server is NULL display error to the user.
//Null could occur if the DB has been stopped or the server is down.
public void GetBalance(string sipUsername)
{
//Remove the underscore ( _ ) from the username, as this is not needed to get the balance.
sipUsername = sipUsername.Remove(0, 1);
string strURL =
string.Format("https://www.xxxxxxx.com",
sipUsername);
//Download only when the webclient is not busy.
if (!wc.IsBusy)
{
// Download the current balance.
wc.DownloadStringAsync(new Uri(strURL));
}
else
{
Console.Write("Busy please try again");
}
}
//return and display the balance after the download has fully completed
void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
//Pass the result to the event handler
}
private bool isDisposed = false;
//Dispose of the balance object
public void Dispose()
{
if (!isDisposed)
Dispose(true);
GC.SuppressFinalize(this);
}
//Remove the event handlers
private void Dispose(bool disposing)
{
isDisposed = true;
if (disposing)
{
wc.DownloadProgressChanged -= new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
wc.DownloadStringCompleted -= new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
wc.Dispose();
}
}
}
,这大部分都是正确的!
编辑:具有该更正的版本:
{{1}}
答案 2 :(得分:3)
由于您已在using语句中声明了wc,因此不应在其外部使用。所以我猜你在GetBalance中使用wc的调用会引发异常。 您应该从Balance contstructor中删除using块。
有关using语句的详细信息,请参阅“using statement (C# Reference)”。
答案 3 :(得分:3)
其他答案是正确的,但他们都错过了你不应该宣布终结者的事实。
来自.Net框架设计指南(第258页):
所以rpetrich的编辑答案是正确的,如果某人有编辑权限,则删除终结者。