C#2008
我一直在研究这个问题,我仍然对一些问题感到困惑.我的问题如下
我知道如果你处理非托管资源,你只需要一个终结器.但是,如果您使用托管资源来调用非托管资源,您是否仍需要实现终结器?
但是,如果您开发一个不直接或间接使用任何非托管资源的类,您是否可以实现IDisposable该类,以便您的类的客户端可以使用'using statement'?
是否可以接受实现IDisposable,以便您的类的客户端可以使用using语句?
using(myClass objClass = new myClass())
{
// Do stuff here
}
Run Code Online (Sandbox Code Playgroud)我在下面开发了这个简单的代码来演示Finalize/dispose模式:
public class NoGateway : IDisposable
{
private WebClient wc = null;
public NoGateway()
{
wc = new WebClient();
wc.DownloadStringCompleted += wc_DownloadStringCompleted;
}
// Start the Async call to find if NoGateway is true or false
public void NoGatewayStatus()
{
// Start the Async's download
// Do other work here
wc.DownloadStringAsync(new Uri(www.xxxx.xxx));
}
private void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
// …Run Code Online (Sandbox Code Playgroud).NET IDisposable Pattern 意味着如果您编写终结器并实现IDisposable,则终结器需要显式调用Dispose.这是合乎逻辑的,而且在极少数情况下我总是会做终结器的保证.
但是,如果我这样做会发生什么:
class Foo : IDisposable
{
public void Dispose(){ CloseSomeHandle(); }
}
Run Code Online (Sandbox Code Playgroud)
并且不要实现终结器或任何东西.框架会为我调用Dispose方法吗?
是的,我意识到这听起来很愚蠢,而且所有的逻辑都暗示它不会,但我总是有两件事让我不确定.
几年前有人曾告诉我,事实上它会这样做,而且那个人有"非常了解他们的东西"的良好记录.
编译器/框架根据您实现的接口(例如:foreach,扩展方法,基于属性的序列化等)执行其他"神奇"操作,因此这也可能是"魔术".
虽然我已经阅读了很多关于它的内容,并且有很多暗示的内容,但我从来没有能够找到这个问题的肯定是或否答案.
如果我不调用此代码段中Dispose的pen对象会发生什么?
private void panel_Paint(object sender, PaintEventArgs e)
{
var pen = Pen(Color.White, 1);
//Do some drawing
}
Run Code Online (Sandbox Code Playgroud) 很多时候,有一个明确的方法,从集合中删除所有项目,这些项目也被处置.
喜欢,
toolStripMenuItem.DropDownItems.Clear();
Run Code Online (Sandbox Code Playgroud)
是足够的,或者我应该这样打电话:
foreach (ToolStripItem item in toolStripMenuItem.DropDownItems)
{
toolStripMenuItem.DropDownItems.Remove(item);
item.Dispose();
}
Run Code Online (Sandbox Code Playgroud)
编辑:好吧ToolStripItem是一个不是问题的例子,对于那些说清楚已经足够的人我发现了另一个例子,TabControl也有项目集合和清除方法.但TabControls可以有复杂的控件(至少我有),需要显式Dispose(即使它们在某些时候由GC自动处理,导致它们占用大量内存).我想最好的答案是divo评论处理项目,然后打电话给清楚.
在大多数情况下,C#编译器似乎可以Dispose()自动调用.像大多数使用模式的情况看起来像:
public void SomeMethod()
{
...
using (var foo = new Foo())
{
...
}
// Foo isn't use after here (obviously).
...
}
Run Code Online (Sandbox Code Playgroud)
因为foo没有使用(这是一个非常简单的检测),并且由于它没有作为参数提供给另一个方法(这是一个适用于许多用例并且可以扩展的假设),编译器可以自动并立即调用Dispose()而无需开发人员需要做到这一点.
这意味着在大多数情况下,using如果编译器做了一些聪明的工作,那么它就没用了.IDisposable似乎低水平足以让我被编译器考虑在内.
现在为什么不这样做?这不会改善性能(如果开发人员...... 很脏).
这对我来说似乎很吵.五行开销太多了.
m_Lock.EnterReadLock()
Try
Return m_List.Count
Finally
m_Lock.ExitReadLock()
End Try
Run Code Online (Sandbox Code Playgroud)
那你怎么这么简单呢?
我问了一个关于这个方法的问题:
// Save an object out to the disk
public static void SerializeObject<T>(this T toSerialize, String filename)
{
XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
TextWriter textWriter = new StreamWriter(filename);
xmlSerializer.Serialize(textWriter, toSerialize);
textWriter.Close();
}
Run Code Online (Sandbox Code Playgroud)
在回复中,我将此作为补充评论:
确保始终处理一次性资源,例如流和文本阅读器和编写器.在SerializeObject方法中似乎不是这种情况.
所以,我可以说,对于那些编写C#一年或两年的人来说,这似乎是非常蹩脚的,但为什么我必须处理它呢?
是看到testWriter有一个dispose方法,但不应该垃圾收集照顾吗?我从Delphi来到C#.在Delphi中我不得不清理所有东西,所以这不是我想要变懒的情况.我刚刚被告知,如果你强行释放你的对象占用的内存,那么它可能会导致坏事.有人告诉我"让垃圾收集器去做".
textWriter击中了磁盘.)这是来自MSDN的代码.我不明白为什么这里的工作不只是在常规的Dispose()方法中完成.使用Dispose(bool)方法的目的是什么?谁会在这里打电话给Dispose(false)?
public void Dispose()
{
Dispose(true);
// Use SupressFinalize in case a subclass
// of this type implements a finalizer.
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
// If you need thread safety, use a lock around these
// operations, as well as in your methods that use the resource.
if (!_disposed)
{
if (disposing) {
if (_resource != null)
_resource.Dispose();
Console.WriteLine("Object disposed.");
}
// Indicate that the instance has been disposed.
_resource = null;
_disposed = …Run Code Online (Sandbox Code Playgroud) 可以创建大量内存密集型对象,然后放弃对它们的引用.例如,我可能想要从数据库下载和操作一些数据,我将进行100次单独的下载和处理迭代.我可以声明一次DataTable变量,并且对于每个查询,使用构造函数将其重置为新的DataTable对象,从而放弃内存中的旧DataTable对象.
DataTable类具有简单的内置方式来释放它使用的内存,包括Rows.Clear()和.Dispose().因此,在将变量设置为新的DataTable对象之前,我可以在每次迭代结束时执行此操作.或者我可以忘掉它,让CLR垃圾收集器为我做这件事.垃圾收集器似乎非常有效,因此最终结果应该是相同的.当你不需要它们时,显然处理内存繁重的对象(但是添加代码来执行此操作)或者只是依靠垃圾收集器为你做所有的工作(你受到了摆布GC算法,但你的代码更小)?
根据要求,这里是代码说明了回收的DataTable变量示例:
// queryList is list of 100 SELECT queries generated somewhere else.
// Each of them returns a million rows with 10 columns.
List<string> queryList = GetQueries(@"\\someserver\bunch-o-queries.txt");
DataTable workingTable;
using (OdbcConnection con = new OdbcConnection("a connection string")) {
using (OdbcDataAdapter adpt = new OdbcDataAdapter("", con)) {
foreach (string sql in queryList) {
workingTable = new DataTable(); // A new table is created. Previous one is abandoned
adpt.SelectCommand.CommandText = sql;
adpt.Fill(workingTable);
CalcRankingInfo(workingTable);
PushResultsToAnotherDatabase(workingTable);
// Here I could call workingTable.Dispose() …Run Code Online (Sandbox Code Playgroud) 我有一个类包含几个为我的MVC应用程序定制的常用方法,我在几个地方使用.这是一些例子:
private MyEntities db = new MyEntities();
public List<SelectListItem> GetLocationList()
{
var query =
db.v_LocationsAlphabetical.OrderByDescending(x => x.Category).ThenBy(x => x.LocationName).ToList()
.Select(x => new SelectListItem
{
Value = x.LocationID.ToString(),
Text = x.LocationName
});
return (query).ToList();
}
public IEnumerable<SelectListItem> GetStates()
{
var query = db.States.Select(x => new SelectListItem
{
Value = x.Abbr,
Text = x.Name
});
return(query);
}
public List<Person> GetPeople()
{
var query = db.Person.OrderBy(m => m.LastName).ThenBy(m => m.FirstName).ToList();
return (query);
}
Run Code Online (Sandbox Code Playgroud)
这些方法中的每一个都调用数据库来获取数据,我想知道是否需要为每个方法添加一个dispose.如果没有,为什么?谢谢.
我有一个或多或少像hastable一样的数组:基于索引,值将放在数组中,因此数组的某些索引将包含值,其他索引可能没有或不会.我有两段代码:
public void register( int index, string value )
{
_array[index] = value;
}
public void unregisterAll( )
{
/*
is this going to cause a memory leak when some of the values
are filled int the above function?
*/
_array = new string[12];
}
Run Code Online (Sandbox Code Playgroud) c# ×9
.net ×6
dispose ×6
idisposable ×3
arrays ×1
clear ×1
collections ×1
database ×1
finalizer ×1
memory-leaks ×1
using ×1
vb.net ×1
winforms ×1