Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 隐式运算符应该处理null吗?_C#_Exception_Implicit Conversion - Fatal编程技术网

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

C# 隐式运算符应该处理null吗?,c#,exception,implicit-conversion,C#,Exception,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 imp

我们有一个类型,它有一个隐式字符串运算符。看起来是这样的:

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);
    }

}
我们刚刚遇到了一个场景,传递给隐式操作符的实例是
null
。显然,我们最终得到了一个
NullReferenceException

我认为这很公平,毕竟,一个类型的字符串表示形式是空的-很难说-所以异常似乎是有效的,我们不应该拦截/抑制/处理/忽略。我的推理是“有人给了我一个空值,我为什么要返回空值?”。我在其他方法中不这样做。我想,‘我知道,在转换它之前,我只需要检查null’,类似于:

字符串s=foo==null?null:foo

但这不起作用,因为它现在在比较为null之前转换为字符串。当然,这种比较是可行的:

Foo f = null;
string s;
if (f != null)
{
    s = f;
}
。。。但那太难看了

我在(一本关于狩猎的“粗略剪裁”书)中读到了这一部分,它说:

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

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

最明显的做法是跳入该方法并将其更改为:

public static implicit operator string(Foo foo)
{
    return foo == null ? null : foo._value;
}

问题解决了。但是我觉得很脏。我感觉通过检查null来隐藏潜在的bug。我是偏执狂/肛门病/愚蠢吗

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

您试图将null强制转换为Foo类型,因为
两侧的类型必须相等

string s = foo == null ? null : foo;
所以你应该使用

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

在隐式转换运算符中“suppress”异常是完全正确的。事实上,正如您所指出的,这是推荐的方法

考虑以下情况:

Foo actualFoo = null;
string stringFoo = actualFoo;
如果编译得很好,为什么要让第二行在运行时抛出异常?那毫无意义

这同样适用于:

string stringFoo = null;
Foo actualFoo = stringFoo;
如果这样定义两个隐式转换运算符,则意味着您希望以与使用typestring相同的方式处理和使用typeFoo。在这种情况下,上述两种情况都是完全有效的构造(您的编译器确认了这一点),应该生成null而不是抛出异常


现在,正如Dan指出的,如果这不是您想要的,那么您需要定义一个显式转换。

我希望
Foo
string
的行为相同。所以,我希望

Foo-Foo=null;
等于(null,foo);
是真的

Equals将尝试将
foo
强制转换为字符串,以便调用隐式运算符。空值
foo
应该公开与空值
字符串
相同的值,即
null

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

公共静态隐式运算符字符串(Foo-Foo)
{
返回foo?\u值;
}

这一切都取决于您的用例。你想让
字符串
为空吗?很好。理想情况下,我们希望永远不会遇到
Foo
的空实例。六羟甲基三聚氰胺六甲醚。。。也许它应该是一个struct…@SteveDunn:一件重要的事情是:
NullReferenceException
总是表示代码中引发异常的bug,而不是调用代码。因此,简单地不检查
foo
是否为
null
是运算符中的一个错误。这也是文档建议的:
string stringFoo = null;
Foo actualFoo = stringFoo;