I am currently creating a struct Nullsafe<T>
that would wrap a reference type (hence T:class
) and behave in a similar way to the Nullable<T> struct
. The point is to emulate something close to what the Option<T>
in F# does.
I intend to use the type in methods which I need to take special care of nulls. For example, assume I have a reference type class Foo
, and the following code:
class Bar
{
public void DoSomethingWithFoo(Nullsafe<Foo> foo);
}
Since I have created an implicit cast operator from T
to Nullsafe<T>
, then the below code would work fine:
Bar bar = new Bar();
Foo nullFoo = null;
bar.DoSomethingWithFoo(nullFoo);
Foo someFoo = new Foo();
bar.DoSomethingWithFoo(someFoo);
The Nullsafe<T>
type is a struct (designed so on purpose, to eliminate passing any null
values directly), therefore it is possible for someone to to write the below snippet:
Nullable<Nullsafe<Foo>> nullableNullsafeFoo = null;
// and later
bar.DoSomethingWithFoo(nullableNullsafeFoo);
The snippet, of cource, will not work.
So, I thought it would be a no-brainer to create a cast operator from within my Nullsafe<T>
struct, which would handle nullable expressions like the above:
public static implicit operator Nullsafe<T>(Nullable<Nullsafe<T>> nv) => nv.GetValueOrDefault();
Unfortunately, this fails to compile. The compiler seems not to make a difference between the Nullsafe<T>
and the Nullable<Nullsafe<T>>
types, and throws at me the message:
Is the above a limitation of the compiler, or is it a purposedly intended behaviour? If so, are there any known workarounds?
error CS0555: User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type
I am using:
dotnet --version
The project is a library multi-targeting different .NET framework versions - from net20 to netstandard2.0
Is the above a limitation of the compiler, or is it a purposedly intended behaviour?
It seems this is indeed a result of the compiler stripping type information, as described by fellow user Isaac van Bakel.
If so, are there any known workarounds?
Doing as he adviced, I submitted an issue to the roslyn platform.
The observed behaviour is in fact intended and confirmed.
A language design discussion thread was created, to address whether this behaviour should be changed in favour of use-cases like the above, or to otherwise provide a better compiler error message to be displayed.