尝试在C#中将演员转换为可空类型时出错

时间:2018-09-08 05:56:46

标签: c# compiler-errors nullable typecast-operator

我当前正在创建一个struct Nullsafe<T>,它将包装一个引用类型(因此为T:class),并且其行为与Nullable<T> struct类似。关键是要模拟一些类似于F#中的Option<T>的东西。

我打算在需要特别注意null的方法中使用类型。例如,假设我具有引用类型class Foo和以下代码:

class Bar
{
    public void DoSomethingWithFoo(Nullsafe<Foo> foo);
}

由于我创建了从TNullsafe<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:用户定义的运算符无法获取封闭类型的对象并将其转换为封闭类型的对象

我正在使用:

  • Visual Studio Community 2017 v15.8.1
  • .NET Sdk v2.1.400(如dotnet --version
  • 所示)

该项目是一个多目标库,面向不同的.NET Framework版本-从net20到netstandard2.0

更新

  

以上是编译器的限制,还是故意的行为?

看来这确实是编译器剥离类型信息的结果,如同行用户Isaac van Bakel所述。

  

如果是,是否有任何已知的解决方法?

按照他的建议,我向roslyn平台提交了an issue

2 个答案:

答案 0 :(得分:1)

根据Roslyn中的代码,尚不清楚这是否确实是预期的。行为来自编译器从强制类型转换中涉及的类型中剥离了Nullable包装程序,以便正确地捕获从Nullable<Foo>Nullable<Foo>的身份强制类型转换-但是在您的情况下,类型之前是不同的剥离,所以应该允许。

您可以在the repository中打开一个问题-我找不到任何已经打开的问题。可以更熟悉编译器设计的人可以参与其中,但这确实像个错误。

答案 1 :(得分:0)

观察到的行为实际上是故意的and confirmed

创建了一种语言设计discussion thread,以解决是否应根据上述用例更改此行为,或者提供更好的编译器错误消息来显示。