隐式运算符应该处理null吗?

Ste*_*unn 10 c# exception-handling implicit-conversion

我们有一个具有隐式字符串运算符的类型.它看起来像这样:

public class Foo
{
    readonly string _value;

    Foo(string value)
    {
        _value = value;
    }

    public static implicit operator string(Foo foo)
    {
        return foo._value;
    }

    public static implicit operator Foo(string fooAsText)
    {
        return new Foo(fooAsText);
    }

}
Run Code Online (Sandbox Code Playgroud)

我们刚刚有一个实例传递给隐式运算符null的场景.显然,我们最终得到了一个NullReferenceException.

我认为这是很公平的,毕竟,什么是一个类型,它是空的字符串表示 - 很难说 - 这样的例外似乎是有效的,这是我们不应该拦截/禁止/手柄/忽略.我的理由是'有人给我一个空的,为什么我应该返回null.我不会在其他方法中这样做.我想,'我知道,我会在转换之前检查null',类似于:

string s = foo == null ? null : foo;

但这没有用,因为它现在在比较之前转换为字符串为null.当然,这种比较可行:

Foo f = null;
string s;
if (f != null)
{
    s = f;
}
Run Code Online (Sandbox Code Playgroud)

......但那只是丑陋的.

我阅读了Essential C#5第4版(Safari上的"Rough Cuts"一书)中的部分,它说:

不要从隐式转换中抛出异常.

这说不抛出异常,但它让我想知道我应该抑制异常吗?

最明显的事情是跳转到方法并将其更改为:

public static implicit operator string(Foo foo)
{
    return foo == null ? null : foo._value;
}
Run Code Online (Sandbox Code Playgroud)

问题解决了.但我觉得很脏.我觉得我通过检查null隐藏了一个潜在的bug.我是偏执狂/肛门/傻瓜吗?

Dan*_*ant 11

在这种情况下我建议的是,失败的运算符应该是显式的而不是隐式的.隐式转换的想法是它正在扩大(即它永远不会失败.)另一方面,显式转换有时会被理解为失败.


com*_*cme 6

我想Foo表现得和一样string。所以,我期望

Foo foo = null;
string.Equals(null, foo);
Run Code Online (Sandbox Code Playgroud)

是真实的。

string.Equals 将尝试转换foo为字符串,因此它将调用隐式运算符。空值foo应该公开与空值相同的值string,即null.

因此,如果您确实想要一个隐式运算符,我会将其实现为:

public static implicit operator string(Foo foo)
{
    return foo?._value;
}
Run Code Online (Sandbox Code Playgroud)