尝试在 C# 中将转换运算符实现为可空类型时出错
Error when trying to implement cast operator to nullable type in C#
我目前正在创建一个 struct Nullsafe<T>
,它将包装一个引用类型(因此 T:class
)并且其行为方式与 Nullable<T> struct
类似。重点是模拟 F# 中 Option<T>
所做的事情。
我打算在需要特别注意空值的方法中使用该类型。例如,假设我有一个引用类型 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>>
类型,并向我抛出消息:
以上是编译器的限制,还是有意为之的行为?如果是这样,是否有任何已知的解决方法?
error CS0555: User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type
我正在使用:
- Visual Studio 社区 2017 v15.8.1
- .NET Sdk v2.1.400(如图
dotnet --version
该项目是一个库,针对不同的 .NET 框架版本 - 从 net20 到 netstandard2.0
更新
Is the above a limitation of the compiler, or is it a purposedly intended behaviour?
这似乎确实是编译器剥离类型信息的结果,正如其他用户所述Isaac van Bakel。
If so, are there any known workarounds?
按照他的建议,我提交了an issue到roslyn平台。
根据 Roslyn 中的代码,尚不清楚这是否确实有意为之。该行为来自编译器从转换中涉及的类型中剥离 Nullable
包装器,以便正确捕获从 Nullable<Foo>
到 Nullable<Foo>
的身份转换 - 但在您的情况下,类型之前不同剥离,所以应该允许。
您可以在 the repository 中打开一个问题 - 我找不到任何已经打开的问题。更熟悉编译器设计的人可以权衡一下,但这确实像是一个错误。
观察到的行为实际上是 and confirmed。
已创建语言设计 discussion thread,以解决是否应更改此行为以支持上述用例,或者以其他方式提供更好的编译器错误消息显示。
我目前正在创建一个 struct Nullsafe<T>
,它将包装一个引用类型(因此 T:class
)并且其行为方式与 Nullable<T> struct
类似。重点是模拟 F# 中 Option<T>
所做的事情。
我打算在需要特别注意空值的方法中使用该类型。例如,假设我有一个引用类型 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>>
类型,并向我抛出消息:
以上是编译器的限制,还是有意为之的行为?如果是这样,是否有任何已知的解决方法?
error CS0555: User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type
我正在使用:
- Visual Studio 社区 2017 v15.8.1
- .NET Sdk v2.1.400(如图
dotnet --version
该项目是一个库,针对不同的 .NET 框架版本 - 从 net20 到 netstandard2.0
更新
Is the above a limitation of the compiler, or is it a purposedly intended behaviour?
这似乎确实是编译器剥离类型信息的结果,正如其他用户所述Isaac van Bakel。
If so, are there any known workarounds?
按照他的建议,我提交了an issue到roslyn平台。
根据 Roslyn 中的代码,尚不清楚这是否确实有意为之。该行为来自编译器从转换中涉及的类型中剥离 Nullable
包装器,以便正确捕获从 Nullable<Foo>
到 Nullable<Foo>
的身份转换 - 但在您的情况下,类型之前不同剥离,所以应该允许。
您可以在 the repository 中打开一个问题 - 我找不到任何已经打开的问题。更熟悉编译器设计的人可以权衡一下,但这确实像是一个错误。
观察到的行为实际上是 and confirmed。
已创建语言设计 discussion thread,以解决是否应更改此行为以支持上述用例,或者以其他方式提供更好的编译器错误消息显示。