c# 空文字 - オブジェクトがnullの場合に空の文字列を返す方法




変換 null判定 (4)

ここに私のコードのスニペットがあります:

var link = socials.Where(p => p.type == Facebook).FirstOrDefault().URL;

問題はリストにソーシャルオブジェクトがないこと.URL FirstOrDefault() null返し、 .URLは例外をトリガーします。

LINQの "one"行でこれを避けるにはどうすればいいですか? したがって、nullが空の"" (またはカスタムの方が良い)文字列を返す場合は、そうでなければ.URL


Answers

引数にDefaultIfEmptyを使用してフォールバック値を指定することができます。

var link = socials
    .Where(p => p.type == Facebook)
    .Select(p => p.Url)
    .DefaultIfEmpty("")
    .First();

FirstOrDefaultはもう必要ではありません、 DefaultIfEmpty Firstを使うのは安全です。


別のオプションは、ヌル結合演算子を使用することです

var link = (socials
    .Where(p => p.type == Facebook)
    .Select(p => p.Url)
    .FirstOrDefault()) ?? string.empty;

私はstring.empty""以上であることを理解しstring.emptyが、 string.emptyはないかもしれません - 下記のコメントを参照してください。

UPDATE C#6には、空の条件演算子(「Elvis」演算子とも呼ばれます)があります。

var link = socials
    .Where(p => p.type == Facebook)
    .Select(p => p.Url)
    .FirstOrDefault()?.URL ?? string.empty;

簡単な例:

stringbuilder sb = null;
// do work
string s = sb?.ToString() ?? "no values found"; 

C#6を使用すると、LINQ文から返されたオブジェクトがnullでない場合、つまり値が見つかった場合、またはnull otherwsieの場合にnull 条件付き演算子?. )を使用してURLを返すことができnull

var link = socials.Where(p => p.type == Facebook).FirstOrDefault()?.URL;

空の文字列またはカスタム文字列にnull値を変更する場合は、 NULL合体演算子?? )を使用します

var link = socials.Where(p => p.type == Facebook).FirstOrDefault()?.URL ?? "No URL";

これは、オブジェクトが見つからなかったか、オブジェクトが見つかったがURL値がnullかどうかを区別しないことに注意してください。


Nullは「問題」ではありません。これはcompleteモデリングツールセットの不可欠な部分です。ソフトウェアは世界の複雑さをモデル化することを目標とし、ヌルはその負担を負っています。Nullは、Javaなどで「データなし」または「不明」を示します。したがって、これらの目的にはnullを使用することが適切です。私は「Nullオブジェクト」パターンを好まない。私はそれが ' 誰が保護者の問題を守るのだろうか?
あなたが私のガールフレンドの名前が何であるか尋ねるなら、私はガールフレンドがいないことをあなたに伝えます。 Java言語ではnullを返します。代わりに、意味のない例外を投げて、あるべき問題を示すことができます(あるいは、どこかで解決しようとしています)、スタックのどこかに委譲して、データアクセスエラーを再試行または報告します。

  1. 「未知の質問」は「未知の答え」を与える。(これがビジネス上の観点から正しいかどうかを確認してください)メソッドの中で一度nullをチェックすると、使用前に複数の呼び出し元が呼び出し前に検査されなくなります。

    public Photo getPhotoOfThePerson(Person person) {
        if (person == null)
            return null;
        // Grabbing some resources or intensive calculation
        // using person object anyhow.
    }
    

    以前は、通常のロジックフローが原因で、存在しないガールフレンドの写真が写真ライブラリから取得されませんでした。

    getPhotoOfThePerson(me.getGirlfriend())
    

    そして、これからのJava APIにも適合します(楽しみにしています)

    getPhotoByName(me.getGirlfriend()?.getName())
    

    むしろ、ある人のためにDBに保存されている写真を見つけるのではなく、「通常のビジネスの流れ」ですが、他のいくつかのケースでは以下のようなペアを使用していました

    public static MyEnum parseMyEnum(String value); // throws IllegalArgumentException
    public static MyEnum parseMyEnumOrNull(String value);
    

    型を嫌うのではなく<alt> + <shift> + <j>(Eclipseでjavadocを生成する)、パブリックAPI用に3つの追加の単語を書く。これは、ドキュメンテーションを読んでいない人以外の人にとっては十分です。

    /**
     * @return photo or null
     */
    

    または

    /**
     * @return photo, never null
     */
    
  2. これはむしろ理論的なケースであり、ほとんどの場合java null安全API(10年後にリリースされる予定です)を優先する必要がありますNullPointerExceptionが、anonymousのサブクラスですExceptionしたがって、これはThrowable合理的なアプリケーションが捕まえたい条件を示す形式です(javadoc)!例外の最初の利点を使い、エラー処理コードを「通常の」コードから分離するには(Javaの作成者によると)、それは私にとっては適切NullPointerExceptionです。

    public Photo getGirlfriendPhoto() {
        try {
            return appContext.getPhotoDataSource().getPhotoByName(me.getGirlfriend().getName());
        } catch (NullPointerException e) {
            return null;
        }
    }
    

    質問が発生する可能性があります:

    Q. getPhotoDataSource()nullが返される場合はどうなりますか?
    A.ビジネスロジックに依存します。私がフォトアルバムを見つけられなかった場合は、あなたに写真は一切表示されません。 appContextが初期化されていない場合はどうなりますか?このメソッドのビジネスロジックはこれを補うものです。同じロジックをより厳密にし、例外をスローする必要がある場合は、ビジネスロジックの一部であり、nullの明示的なチェックを使用する必要があります(ケース3)。新しいJavaヌル安全なAPIを初期化するために意味するものではありません。何を意味し、どのような選択を指定するには、ここより良いフィットフェイルファストプログラマのエラーの場合にあるように。

    Q.冗長コードが実行され、不要なリソースを取得する可能性があります。
    A. getPhotoByName()データベース接続を開こうとするPreparedStatementと、最後に人の名前をSQLパラメータとして作成して使用することができます。未知の質問に対するアプローチは、未知の答えを与える(ケース1)ここで働く。リソースを取得する前に、メソッドはパラメータをチェックし、必要に応じて「不明な」結果を返す必要があります。

    Q.このアプローチには、クロージャーの試行を試みることによるパフォーマンスの低下があります。
    A.ソフトウェアは最初に理解して変更するのが簡単です。この後、必要な場合にのみ、パフォーマンスについて考えることができます。必要に応じて!(source)、その他多数)。

    PS。このアプローチは、「通常の」コード原則とは別のエラー処理コードを使用するのが妥当で、ある場所で使用するのが妥当です。次の例を考えてみましょう。

    public SomeValue calculateSomeValueUsingSophisticatedLogic(Predicate predicate) {
        try {
            Result1 result1 = performSomeCalculation(predicate);
            Result2 result2 = performSomeOtherCalculation(result1.getSomeProperty());
            Result3 result3 = performThirdCalculation(result2.getSomeProperty());
            Result4 result4 = performLastCalculation(result3.getSomeProperty());
            return result4.getSomeProperty();
        } catch (NullPointerException e) {
            return null;
        }
    }
    
    public SomeValue calculateSomeValueUsingSophisticatedLogic(Predicate predicate) {
        SomeValue result = null;
        if (predicate != null) {
            Result1 result1 = performSomeCalculation(predicate);
            if (result1 != null && result1.getSomeProperty() != null) {
                Result2 result2 = performSomeOtherCalculation(result1.getSomeProperty());
                if (result2 != null && result2.getSomeProperty() != null) {
                    Result3 result3 = performThirdCalculation(result2.getSomeProperty());
                    if (result3 != null && result3.getSomeProperty() != null) {
                        Result4 result4 = performLastCalculation(result3.getSomeProperty());
                        if (result4 != null) {
                            result = result4.getSomeProperty();
                        }
                    }
                }
            }
        }
        return result;
    }
    

    PPS。それらを高速でdownvote(とドキュメントを読むにはあまり速くない)私は私の人生でnullポインタ例外(NPE)を捕まえたことはないと言いたいと思います。しかし、この可能性は、Javaクリエイターによって意図的に設計されたものですException。なぜなら、NPEはJavaクリエイターのサブクラスであるからです。ときに我々は、Javaの歴史の中で先例を持ってThreadDeathいるError、それは実際にアプリケーション・エラーであるためではないが、それが捕捉されることを意図していなかっただけであるため、!どのくらいのNPEがあることをフィットErrorよりもThreadDeath!そうではありません。

  3. ビジネスロジックが意味する場合のみ「データなし」をチェックします。

    public void updatePersonPhoneNumber(Long personId, String phoneNumber) {
        if (personId == null)
            return;
        DataSource dataSource = appContext.getStuffDataSource();
        Person person = dataSource.getPersonById(personId);
        if (person != null) {
            person.setPhoneNumber(phoneNumber);
            dataSource.updatePerson(person);
        } else {
            Person = new Person(personId);
            person.setPhoneNumber(phoneNumber);
            dataSource.insertPerson(person);
        }
    }
    

    そして

    public void updatePersonPhoneNumber(Long personId, String phoneNumber) {
        if (personId == null)
            return;
        DataSource dataSource = appContext.getStuffDataSource();
        Person person = dataSource.getPersonById(personId);
        if (person == null)
            throw new SomeReasonableUserException("What are you thinking about ???");
        person.setPhoneNumber(phoneNumber);
        dataSource.updatePerson(person);
    }
    

    appContextまたはdataSourceが未処理のランタイムNullPointerExceptionによって初期化されていない場合、現在のスレッドが終了し、Thread.defaultUncaughtExceptionHandlerによって処理されThread.defaultUncaughtExceptionHandler(お気に入りのロガーまたはその他の通知Thread.defaultUncaughtExceptionHandlerを定義して使用するため)。設定されていない場合、ThreadGroup#uncaughtExceptionはstacktraceをシステムerrに出力します。アプリケーションエラーログを監視し、実際にはアプリケーションエラーである未処理例外ごとにJira問題をオープンする必要があります。プログラマは、初期化作業のどこかでバグを修正するべきです。





c# .net string linq null