Also Ihr grundsätzliches Problem hier ist, dass Sie eine unbestimmte Anzahl von IDisposable
Objekte erstellen, und Sie sind nicht sicher, wenn Sie bereit sein, sie zu schließen. In einer solchen Situation erstelle ich eine Sammlung, um sie zu verfolgen und dann alles in der Sammlung zu entsorgen, wenn ich fertig bin. Hier besteht die Gefahr, dass Sie Ihre Objekte nicht ordnungsgemäß entsorgen.
public static string QueryRegistry (RegistryKey root, string path)
{
List<IDisposable> resourceTracker = new List<IDisposable>() { root };
string ret = null;
try
{
ret = path.Split(Path.DirectorySeparatorChar)
.Aggregate(root, (r, k) =>
{
var key = r?.OpenSubKey(k);
if (key != null)
{
resourceTracker.Add(key);
}
return key;
}).GetValue(null).ToString();
}
finally
{
foreach (var res in resourceTracker)
{
res.Dispose();
}
}
return ret;
}
Sie könnten versuchen, dies in einer CER zu tun, aber ich bin mir ziemlich sicher, öffnen die neuen Schlüssel als Zuteilungen zählen, die die CLR bedeuten würde es nicht behandeln als CER sowieso. Aber das sollte wahrscheinlich sicher genug sein.
Dies könnte in einer Sammlung abstrahiert werden (so etwas wie rory.ap vorgeschlagen) wie folgt:
public class DisposableCollection : IList<IDisposable>, IDisposable
{
private List<IDisposable> disposables = new List<IDisposable>();
#region IList<IDisposable> support
public int Count
{
get
{
return ((IList<IDisposable>)disposables).Count;
}
}
public bool IsReadOnly
{
get
{
return ((IList<IDisposable>)disposables).IsReadOnly;
}
}
public int IndexOf(IDisposable item)
{
return ((IList<IDisposable>)disposables).IndexOf(item);
}
public void Insert(int index, IDisposable item)
{
((IList<IDisposable>)disposables).Insert(index, item);
}
public void RemoveAt(int index)
{
((IList<IDisposable>)disposables).RemoveAt(index);
}
public void Add(IDisposable item)
{
((IList<IDisposable>)disposables).Add(item);
}
public void Clear()
{
((IList<IDisposable>)disposables).Clear();
}
public bool Contains(IDisposable item)
{
return ((IList<IDisposable>)disposables).Contains(item);
}
public void CopyTo(IDisposable[] array, int arrayIndex)
{
((IList<IDisposable>)disposables).CopyTo(array, arrayIndex);
}
public bool Remove(IDisposable item)
{
return ((IList<IDisposable>)disposables).Remove(item);
}
public IEnumerator<IDisposable> GetEnumerator()
{
return ((IList<IDisposable>)disposables).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IList<IDisposable>)disposables).GetEnumerator();
}
public void AddRange(IEnumerable<IDisposable> range)
{
disposables.AddRange(range);
}
public IDisposable this[int index]
{
get
{
return ((IList<IDisposable>)disposables)[index];
}
set
{
((IList<IDisposable>)disposables)[index] = value;
}
}
#endregion
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
foreach(var disposable in disposables)
{
disposable.Dispose();
}
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
disposedValue = true;
}
}
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
// ~DisposableCollection() {
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
// Dispose(false);
// }
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion
}
die dann wie verwendet werden könnten:
public static string QueryRegistry (RegistryKey root, string path)
{
string ret = null;
using (var resourceTracker = new DisposableCollection() { root })
{
ret = path.Split(Path.DirectorySeparatorChar)
.Aggregate(root, (r, k) =>
{
var key = r?.OpenSubKey(k);
if (key != null)
{
resourceTracker.Add(key);
}
return key;
}).GetValue(null).ToString();
}
return ret;
}
Diese Klasse ein wenig verlängert werden könnte auch in konkurrierenden Situationen zu arbeiten (sagen wir mit ConcurrentBag
oder ConcurrentQueue
), und könnte für andere spezifische Bedürfnisse (wie eine Sammlung von RegistryKey
s) erweitert werden, und wäre nützlich, wenn Sie diese Logik an mehreren Orten benötigen.
'RegistryKey' ist' IDisposable': http://Stackoverflow.com/a/9905046/1132334. [this] (https://msdn.microsoft.com/en-us/library/microsoft.win32.registrykey (v = vs.90) .aspx) schlägt vor, dass es ausreicht, den obersten Schlüssel in 'using' zu legen. – dlatikay
@dlatikay, wo es darauf hindeutet, dass es ausreicht, nur Root-Schlüssel zu entsorgen? – Evk
Ok, ja, ich wusste, dass es "IDisposable" war, aber ich war mir nicht sicher, wie man eine using-Anweisung auf Funktionsaufrufe anwenden konnte. Warum nur der oberste Schlüssel? –