C# in Depth

Cover of C# in Depth
Order now (3rd edition)

Derivation type constraints and implicit reference conversions

Chapter 3: Parameterized typing with generics: 3.3.1

Created: 1/28/2008
Last updated: 1/28/2008

The footnote regarding implicit reference conversions is a good example of why it was so great to have Eric Lippert reviewing the book. You see, I originally had this (broken) example in mind:

// Broken code - do not use
using System;
using System.IO;

public class FakeStream
{
    public static implicit operator Stream(FakeStream original)
    {
        return new MemoryStream();
    }
}

class Test
{
    static void ShowLength<T>(T input) where T : Stream
    {
        Console.WriteLine (typeof(T));
        Console.WriteLine (input.Length);
    }
    
    static void Main()
    {
        FakeStream x = new FakeStream();
        // This line is okay, but it's not an implicit reference conversion
        Stream s = x;
        // Compilation error!
        ShowLength(x);
    }
}

Now, I thought this would compile, because there's an implicit conversion from an expression of type FakeStream to Stream as shown by the line with s in it. The input of that conversion is a reference and the output is a reference.

That doesn't mean it's an implicit reference conversion though. The terminology is slightly confusing here - but basically an implicit reference conversion is one where the CLR can just use the original pointer (reference) itself as a pointer (reference) to an instance of the target type. So, this works for things like interfaces and arrays. It doesn't work when the conversion returns a completely different reference, as user-defined conversions generally do.