Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy doesn't this use of implicit casts work?
    primarykey
    data
    text
    <p>I've defined a generic class "<code>Lazy&lt;T&gt;</code>", for lazy evaluation and caching of the result of a delegate <code>Func&lt;T&gt;</code>.</p> <p>I also define two implicit cast operators so I can create a <code>Lazy&lt;T&gt;</code> from a <code>Func&lt;T&gt;</code>s, and I can assign a <code>Lazy&lt;T&gt;</code> to a <code>T</code> (gets the <code>Value</code> of the <code>Lazy&lt;T&gt;</code>)</p> <p>The idea is that you can pass around a <code>Lazy&lt;T&gt;</code> in place of an instance of <code>T</code>, but not do the work to calculate/retrieve the value until it is assigned to an actual instance of <code>T</code>.</p> <pre><code>// class Lazy&lt;T&gt; // Encapsulates a value which can be retrieved when first accessed, // and is then cached. class Lazy&lt;T&gt; { private Func&lt;T&gt; _getter; private T _cached; private bool _isCached; // Get/set the getter delegate // that 'calculates' the value. public Func&lt;T&gt; 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&lt;T&gt; public static implicit operator T(Lazy&lt;T&gt; lazy) { return lazy.Value; } // Create a Lazy&lt;T&gt; from a Func&lt;T&gt; public static implicit operator Lazy&lt;T&gt;(Func&lt;T&gt; getter) { return new Lazy&lt;T&gt; {Getter = getter}; } } </code></pre> <p>But this class doesn't work as I expected in one case, highlighted in the test app below:</p> <pre><code>class Program { static void Main() { // This works okay (1) TestLazy(() =&gt; MakeStringList()); // This also works (2) Lazy&lt;string&gt; lazyString = new Func&lt;string&gt;(() =&gt; "xyz"); string s = lazyString; //This doesn't compile (3) // Lazy&lt;IList&lt;string&gt;&gt; lazyStrings = new Func&lt;IList&lt;string&gt;&gt;(MakeStringList); IList&lt;string&gt; strings = lazyStrings; //ERROR } static void TestLazy&lt;T&gt;(Func&lt;T&gt; getter) { Lazy&lt;T&gt; lazy = getter; T nonLazy = lazy; } private static IList&lt;string&gt; MakeStringList() { return new List&lt;string&gt; { new string('-', 10) }; } } </code></pre> <p>On the line marked with <code>//ERROR</code>, I get a compile error:</p> <p><strong>error CS0266: Cannot implicitly convert type <code>Lazy&lt;System.Collections.Generic.IList&lt;string&gt;&gt;</code> to <code>System.Collections.Generic.IList&lt;string&gt;</code>. An explicit conversion exists (are you missing a cast?)</strong></p> <p>This error is confusing as there does exist an implicit cast from the source to the target type in question. And, on the face of it, code chunk (3) is doing the same thing as (1) Also, it differs from (2) only by the type used to specialize the Lazy.</p> <p>Can anyone explain to me what's going on here?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload