我当前正在创建一个struct Nullsafe<T>
,它将包装一个引用类型(因此为T:class
),并且其行为与Nullable<T> struct
类似。关键是要模拟一些类似于F#中的Option<T>
的东西。
我打算在需要特别注意null的方法中使用类型。例如,假设我具有引用类型class Foo
和以下代码:
class Bar
{
public void DoSomethingWithFoo(Nullsafe<Foo> foo);
}
由于我创建了从T
到Nullsafe<T>
的隐式强制转换运算符,因此以下代码可以正常工作:
Bar bar = new Bar();
Foo nullFoo = null;
bar.DoSomethingWithFoo(nullFoo);
Foo someFoo = new Foo();
bar.DoSomethingWithFoo(someFoo);
Nullsafe<T>
类型是一种结构(有意设计为避免直接传递任何null
值),因此有人可以编写以下代码段:
Nullable<Nullsafe<Foo>> nullableNullsafeFoo = null;
// and later
bar.DoSomethingWithFoo(nullableNullsafeFoo);
当然,该代码段将无效。
因此,我认为从我的Nullsafe<T>
结构中创建一个强制转换运算符将是一件容易的事,该运算符将处理上述可空表达式:
public static implicit operator Nullsafe<T>(Nullable<Nullsafe<T>> nv) => nv.GetValueOrDefault();
不幸的是,这无法编译。编译器似乎在Nullsafe<T>
和Nullable<Nullsafe<T>>
类型之间没有任何区别,并向我抛出了一条消息:
以上内容是对编译器的限制,还是故意的行为?如果是这样,是否有任何已知的解决方法?
错误CS0555:用户定义的运算符无法获取封闭类型的对象并将其转换为封闭类型的对象
我正在使用:
dotnet --version
该项目是一个多目标库,面向不同的.NET Framework版本-从net20到netstandard2.0
以上是编译器的限制,还是故意的行为?
看来这确实是编译器剥离类型信息的结果,如同行用户Isaac van Bakel所述。
如果是,是否有任何已知的解决方法?
按照他的建议,我向roslyn平台提交了an issue。
答案 0 :(得分:1)
根据Roslyn中的代码,尚不清楚这是否确实是预期的。行为来自编译器从强制类型转换中涉及的类型中剥离了Nullable
包装程序,以便正确地捕获从Nullable<Foo>
到Nullable<Foo>
的身份强制类型转换-但是在您的情况下,类型之前是不同的剥离,所以应该允许。
您可以在the repository中打开一个问题-我找不到任何已经打开的问题。可以更熟悉编译器设计的人可以参与其中,但这确实像个错误。
答案 1 :(得分:0)
观察到的行为实际上是故意的and confirmed。
创建了一种语言设计discussion thread,以解决是否应根据上述用例更改此行为,或者提供更好的编译器错误消息来显示。