Я определил общий класс "Lazy<T>
", для ленивой оценки и кэширования результата делегата Func<T>
.
Я также определяю два неявных оператора трансляции, поэтому я могу создать Lazy<T>
из Func<T>
s, и я могу назначить Lazy<T>
a T
(получает Value
Lazy<T>
)
Идея состоит в том, что вы можете передать Lazy<T>
вместо экземпляра T
, но не выполнять работу по вычислению/извлечения значения до тех пор, пока он не будет назначен фактическому экземпляру T
.
// class Lazy<T>
// Encapsulates a value which can be retrieved when first accessed,
// and is then cached.
class Lazy<T>
{
private Func<T> _getter;
private T _cached;
private bool _isCached;
// Get/set the getter delegate
// that 'calculates' the value.
public Func<T> Getter
{
get
{
return _getter;
}
set
{
_getter = value;
_cached = default(T);
_isCached = false;
}
}
// Get/set the value.
public T Value
{
get
{
if (!_isCached)
{
_cached = Getter();
_isCached = true;
_getter = null;
}
return _cached;
}
set
{
_cached = value;
_isCached = true;
_getter = null;
}
}
// Implicit casts:
// Create a T from a Lazy<T>
public static implicit operator T(Lazy<T> lazy)
{
return lazy.Value;
}
// Create a Lazy<T> from a Func<T>
public static implicit operator Lazy<T>(Func<T> getter)
{
return new Lazy<T> {Getter = getter};
}
}
Но этот класс не работает, как я ожидал, в одном случае, который показан в тестовом приложении ниже:
class Program
{
static void Main()
{
// This works okay (1)
TestLazy(() => MakeStringList());
// This also works (2)
Lazy<string> lazyString = new Func<string>(() => "xyz");
string s = lazyString;
//This doesn't compile (3)
//
Lazy<IList<string>> lazyStrings = new Func<IList<string>>(MakeStringList);
IList<string> strings = lazyStrings; //ERROR
}
static void TestLazy<T>(Func<T> getter)
{
Lazy<T> lazy = getter;
T nonLazy = lazy;
}
private static IList<string> MakeStringList()
{
return new List<string> { new string('-', 10) };
}
}
В строке, помеченной //ERROR
, я получаю ошибку компиляции:
ошибка CS0266: Невозможно неявно преобразовать тип Lazy<System.Collections.Generic.IList<string>>
в System.Collections.Generic.IList<string>
. Явное преобразование существует (вы пропускаете листинг?)
Эта ошибка сбивает с толку, поскольку существует неявный перевод из источника в заданный тип. И, на первый взгляд, блок кода (3) делает то же самое, что (1) Кроме того, он отличается от (2) только типом, используемым для специализации Lazy.
Может кто-нибудь объяснить мне, что здесь происходит?