Есть ли в .NET Framework какой-либо класс, представляющий контейнер хранения объектов?
-
04-10-2019 - |
Вопрос
Я ищу класс, который определяет структуру хранения объекта.Значение для этого объекта может быть установлено позже, чем при создании этого контейнера.Полезно передавать такую структуру в лямбды, функции обратного вызова и т. д.
Сказать:
class HoldObject<T> {
public T Value { get; set; }
public bool IsValueSet();
public void WaitUntilHasValue();
}
// and then we could use it like so ...
HoldObject<byte[]> downloadedBytes = new HoldObject<byte[]>();
DownloadBytes("http://www.stackoverflow.com", sender => downloadedBytes.Value = sender.GetBytes());
Определить эту структуру довольно легко, но я пытаюсь выяснить, доступна ли она в FCL.Я также хочу, чтобы это была эффективная структура со всеми необходимыми функциями, такими как потокобезопасность, эффективное ожидание и т. д.
Любая помощь очень ценится.
Решение
Никогда не видел такого класса, но он должен быть довольно простым.
public class ObjectHolder<T>
{
private T value;
private ManualResetEvent waitEvent = new ManualResetEvent(false);
public T Value
{
get { return value; }
set
{
this.value = value;
ManualResetEvent evt = waitEvent;
if(evt != null)
{
evt.Set();
evt.Dispose();
evt = null;
}
}
}
public bool IsValueSet
{
get { return waitEvent == null; }
}
public void WaitUntilHasValue()
{
ManualResetEvent evt = waitEvent;
if(evt != null) evt.WaitOne();
}
}
Другие советы
То, чего вы пытаетесь достичь, очень похоже на будущее.Ранние версии CTP .NET 4.0 TPL имели Future<T>
сорт.В окончательной первоначальной версии .NET 4.0 он был переименован в Task<T>
.Если прищуриться, то можно увидеть сходство между:
class HoldObject<T>
{
public T Value { get; set; }
public bool IsValueSet();
public void WaitUntilHasValue();
}
и
class Task<T>
{
public T Value { get }
public bool IsCompleted { get; }
public void Wait();
}
Если вы еще не используете .NET 4.0, вы можете загрузить Реактивные расширения для .NET 3.5sp1.Он содержит сборку System.Threading.dll, содержащую TPL для .NET 3.5.
В то время
Value
доступен только для чтения, его изменение, конечно, можно выполнить с помощью возвращаемого значения делегата, который вы предоставляете задаче.Я, конечно, не совсем уверен, соответствует ли это вашим требованиям, но ваш пример можно записать так:
var downloadBytesTask = Task<byte[]>.Factory.StartNew(() =>
DownloadBytes("http://www.stackoverflow.com"));
if (!downloadBytesTask.IsCompleted)
{
downloadBytesTask.Wait();
}
var bytes = downloadBytesTask.Value;