15

暗黙の文字列演算子を持つ型があります。次のようになります。

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である型の文字列表現は何であるか(言うのは難しいです)、例外は有効であるように見え、傍受/抑制/処理/無視すべきではありません。私の推論は、誰かが私にnullを与えたという線に沿っていました、なぜ私はnullを返す必要があります。私は他の方法ではこれをしません。私は、「わかっている、変換する前にnullをチェックするだけだ」と思った。

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

しかし、 nullと比較するに文字列に変換されているため、これは機能しませんでした。もちろん、この比較は機能します。

Foo f = null;
string s;
if (f != null)
{
    s = f;
}

...しかしそれはただ醜いです。

Essential C#5第4版(Safariの「ラフカット」の本)のセクションを読んだところ、次のように書かれています。

暗黙の変換から例外をスローしないでください。

これは、例外をスローしないことを示していますが、例外を抑制すべきかどうか疑問に思います。

最も明白なことは、メソッドにジャンプして次のように変更することです。

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

問題が解決しました。しかし、私は汚い感じがします。nullをチェックすることで、潜在的なバグを隠しているような気がします。私は妄想/アナル/愚かですか?

4

4 に答える 4

13

この場合に私がお勧めするのは、失敗する可能性のある演算子は暗黙的ではなく明示的であるべきだということです。暗黙的な変換の考え方は、それが拡大する (つまり、決して失敗しない) ということです。一方、明示的な変換は、時々失敗する可能性があると理解されています。

于 2012-11-29T14:32:08.540 に答える
5

Foo私はと同じように行動したいと思いstringます。だから、私は期待したい

Foo foo = null;
string.Equals(null, foo);

真であります。

string.Equals はfoo文字列にキャストしようとするため、暗黙の演算子が呼び出されます。nullfoo値は、null 値と同じ値を公開する必要stringがありnullます。

したがって、暗黙の演算子が必要な場合は、次のように実装します。

public static implicit operator string(Foo foo)
{
    return foo?._value;
}
于 2020-02-07T07:15:03.383 に答える
0

暗黙の変換演算子内で例外を「抑制する」ことはまったく問題ありません。実際、あなたが指摘したように、それが推奨されるアプローチです。

次のシナリオを検討してください。

Foo actualFoo = null;
string stringFoo = actualFoo;

これが問題なくコンパイルされた場合、実行時に 2 行目で例外をスローする必要があるのはなぜですか? それは意味がありません。

これについても同じことが言えます:

string stringFoo = null;
Foo actualFoo = stringFoo;

両方の暗黙的な変換演算子をそのように定義している場合は、型Fooをstring型を使用するのと同じように扱い、使用する必要があることを意味します。その場合、上記の両方のシナリオは完全に有効な構造であり (コンパイラーがそれを確認します)、例外をスローするのではなく null を生成する必要があります。

さて、ダンが指摘したように、これがあなたの望むものでないなら、代わりに明示的な変換を定義する必要があります。

于 2019-01-28T13:43:35.530 に答える