Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit conversion with a generic type failing for an interface type

        private struct Maybe<T>
        {
            private readonly T value;
            private readonly bool hasValue;

            private Maybe(T value)
            {
                this.value = value;
                hasValue = true;
            }

            public static implicit operator Maybe<T>(T value) =>
                value == null ? new Maybe<T>() : new Maybe<T>(value);
        }

        private static Maybe<byte> OK()
        {
            return 5;
        }

        private static Maybe<IEnumerable<byte>> NotOK()
        {
            var e = new[] { 1, 2, 3 }.Select(x => (byte)x);
            Console.WriteLine(e.GetType().Name);
            return e;
        }

Fiddle (don't use): https://dotnetfiddle.net/NxAw9l

Updated fiddle: https://dotnetfiddle.net/NrARTl

Some generic type is failing for implicit conversion at above code. See the Ok() and NotOk() function calls and return types. A complex generic type is failing and I dont' understand why. I have simplified this from a function of a return type of IEnumerable<IEnumerable<T>>. This IEnumerable<T> still fails. I think If I can understand why this fails, I'd solve the real one too I suppose. Thanks for your help and time.

Here is the error message if you'd like:

Error    CS0029    Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<byte>' to 'Maybe<System.Collections.Generic.IEnumerable<byte>>'

Update: Returning Byte[] from the NotOK() can't work because in my real source code I have a LINQ query I have to depend on its lazy-deferred execution (i.e It has to be strictly returning IEnumerable) (see alike answer => https://stackoverflow.com/a/63880804/5917087).

like image 425
Emirhan Özlen Avatar asked Mar 03 '23 02:03

Emirhan Özlen


1 Answers

The C# standard currently does not allow implicit conversions from or to interfaces.

This is a well-known problem when implementing a Maybe<T> (or Optional<T>, as it is often called) type in C#. There is an ongoing discussion about this on the C# language github forum:

  • https://github.com/dotnet/roslyn/issues/14186

As a workaround, you could make the Maybe<T> constructor internal and add a static non-generic helper class:

private static class Maybe
{
    public static Maybe<T> From<T>(T value) => 
        value == null ? new Maybe<T>() : new Maybe<T>(value);
}

which allows you to use type inference and write Maybe.From(a), which is a bit shorter than new Maybe<IEnumerable<byte>>(a).

like image 55
Heinzi Avatar answered Mar 22 '23 22:03

Heinzi