¿Por qué no funciona este uso de moldes implícitos?
He definido una clase genérica "Lazy<T>
", para la evaluación perezosa y el almacenamiento en caché del resultado de un delegadoFunc<T>
.
También defino dos operadores de conversión implícitos para poder crear unLazy<T>
a partir de unaFunc<T>
s, y puedo asignar unLazy<T>
a unT
(obtiene elValue
delLazy<T>
)
La idea es que puedas pasar unaLazy<T>
en lugar de una instancia deT
, pero no realice el trabajo para calcular / recuperar el valor hasta que se asigne a una instancia real deT
.
// 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};
}
}
Pero esta clase no funciona como esperaba en un caso, resaltada en la aplicación de prueba a continuación:
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) };
}
}
En la línea marcada con//ERROR
, Me sale un error de compilación:
error CS0266: no se puede convertir implícitamente el tipoLazy<System.Collections.Generic.IList<string>>
aSystem.Collections.Generic.IList<string>
. Existe una conversión explícita (¿falta un elenco?)
Este error es confuso ya que existe una conversión implícita del origen al tipo de destino en cuestión. Y, a primera vista, el fragmento de código (3) está haciendo lo mismo que (1) Además, difiere de (2) solo por el tipo utilizado para especializar a los perezosos.
¿Puede alguien explicarme lo que está pasando aquí?