代码之家  ›  专栏  ›  技术社区  ›  mackenir

为什么这种隐式类型转换的使用不起作用?

  •  10
  • mackenir  · 技术社区  · 17 年前

    我定义了一个通用类” Lazy<T> “,用于延迟评估和缓存委托的结果 Func<T> .

    我还定义了两个隐式强制转换运算符,以便创建 懒惰&懒惰; 从A F&C;T & GT; S,我可以指定 懒惰&懒惰; 到A T (得到 Value 的 懒惰&懒惰; )

    你可以通过一个 懒惰&懒惰; 代替 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)的区别仅仅在于用于专门化懒惰的类型。

    有人能告诉我这里发生了什么事吗?

    2 回复  |  直到 17 年前
        1
  •  17
  •   Jon Skeet    17 年前

    IList<T>

    Lazy<List<T>>

    object strings = lazyStrings;
    

    List<T> object

    class ListLazy : Lazy<IList<string>>, IList<string>
    {
        // Stuff
    }
    ...
    Lazy<IList<string>> x = new ListLazy();
    IList<string> list = x;
    

    IList<string> Lazy<IList<string>>

        2
  •  3
  •   Henk Holterman    17 年前

    Lazy<List<string>> lazyStrings = new Func<List<string>>(MakeStringList);
    IList<string> strings = lazyStrings; //ERROR
    List<string> strings = lazyStrings; //OK
    

    IList<string> istrings = strings;