Dlaczego nie działa to w sposób niejawny?

Zdefiniowałem klasę ogólną ”Lazy<T>„, dla leniwej oceny i buforowania wyniku delegataFunc<T>.

Definiuję także dwa niejawne operatory rzutowania, dzięki czemu mogę utworzyćLazy<T> odFunc<T>s, a ja mogę przypisaćLazy<T> do aT (dostajeValue zLazy<T>)

Chodzi o to, że możesz omijaćLazy<T> w miejsce wystąpieniaT, ale nie wykonuj pracy, aby obliczyć / pobrać wartość, dopóki nie zostanie przypisana do rzeczywistej instancjiT.

// 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};
  }
}

Ale ta klasa nie działa tak, jak oczekiwałem w jednym przypadku, zaznaczona w poniższej aplikacji testowej:

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) };
  }
}

Na linii oznaczonej//ERROR, Dostaję błąd kompilacji:

błąd CS0266: Nie można niejawnie przekonwertować typuLazy<System.Collections.Generic.IList<string>> doSystem.Collections.Generic.IList<string>. Istnieje jawna konwersja (czy brakuje Ci rzutu?)

Ten błąd jest mylący, ponieważ istnieje niejawny rzut od źródła do danego typu docelowego. Na pierwszy rzut oka fragment kodu (3) robi to samo co (1). Różni się także od (2) tylko typem używanym do specjalizacji Lazy.

Czy ktoś może mi wyjaśnić, co tu się dzieje?

questionAnswers(2)

yourAnswerToTheQuestion