つい最近、数人の同僚がメモリ リークの絞り込みを手伝ってくれました。問題の 1 つは Microsoft のコードで見つかりました。これは、列挙子がリークすることを示すリフレクターからのものです。
ここで count プロパティは getenumerator を呼び出しますが、Idisposable をチェックしません:
public int Count
{
get
{
if (this.isDisposed)
{
throw new ObjectDisposedException(name);
}
int num = 0;
IEnumerator enumerator = this.GetEnumerator();
while (enumerator.MoveNext())
{
num++;
}
return num;
}
}
これは、返される型が ManagementObjectEnumerator であることを示すための ManagementObjectCollection の GetEnumerator です。
public ManagementObjectEnumerator GetEnumerator()
{
if (this.isDisposed)
{
throw new ObjectDisposedException(name);
}
if (!this.options.Rewindable)
{
return new ManagementObjectEnumerator(this, this.enumWbem);
}
IEnumWbemClassObject ppEnum = null;
int errorCode = 0;
try
{
errorCode = this.scope.GetSecuredIEnumWbemClassObjectHandler(this.enumWbem).Clone_(ref ppEnum);
if ((errorCode & 0x80000000L) == 0L)
{
errorCode = this.scope.GetSecuredIEnumWbemClassObjectHandler(ppEnum).Reset_();
}
}
catch (COMException exception)
{
ManagementException.ThrowWithExtendedInfo(exception);
}
if ((errorCode & 0xfffff000L) == 0x80041000L)
{
ManagementException.ThrowWithExtendedInfo((ManagementStatus) errorCode);
}
else if ((errorCode & 0x80000000L) != 0L)
{
Marshal.ThrowExceptionForHR(errorCode);
}
return new ManagementObjectEnumerator(this, ppEnum);
}
これは、使い捨てであることを示しています。
public class ManagementObjectEnumerator : IEnumerator, IDisposable
{
// Fields
private bool atEndOfCollection;
private uint cachedCount;
private IWbemClassObjectFreeThreaded[] cachedObjects;
private int cacheIndex;
private ManagementObjectCollection collectionObject;
private IEnumWbemClassObject enumWbem;
private bool isDisposed;
private static readonly string name;
// Methods
static ManagementObjectEnumerator();
internal ManagementObjectEnumerator(ManagementObjectCollection collectionObject, IEnumWbemClassObject enumWbem);
public void Dispose();
protected override void Finalize();
public bool MoveNext();
public void Reset();
// Properties
public ManagementBaseObject Current { get; }
object IEnumerator.Current { [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get; }
}
破棄可能な列挙子は foreach ステートメント (http://msdn.microsoft.com/en-us/library/aa664754(v=vs.71).aspx) によって適切に破棄されますが、これは、列挙子は foreach ループで使用されます。
count プロパティをスキップして、列挙子を自分で使用してコレクション内のオブジェクトの数を取得する独自のメカニズムを実行できることは知っていますが、質問は、これによってどれだけのアンマネージ メモリがリークするかということです。