bugfix> c# > 投稿

私は明白な何かを忘れていると思うが、可能な限り乾燥したままの状態を検証する場合、値を割り当てる方法を見つけることができないようです... 私が意味することを説明するいくつかのコード...

a = (b > 1) ? b : c;

またはさらに a = (a > 1) ? a : b;

だからもちろんここでは大したことではないが、もしaがメソッド呼び出し(多分そこのyield return)に置き換えられるとしたら、それを2回呼び出さなければならないだろう...

私が見るのは、上記のコードのようになる変数に格納しているだけです...

より良いアイデアはありますか?

理解を深めるために編集: nullチェック(?。?[])などを使用してxmlファイルの値を検索するとします。

string store_no = myXmlNode.SelectSingleNode("aChildNode")?.SelectSingleNode("myNode")?.Attributes?["store_no]?.Value;

したがって、ここで変数に保存して、後でその値をテストできるようにします。 特定のstore_noを確認したい場合は、次のようなことをする必要があります。

store_no = (store_no=="STORE23")? store_no : "unknown";

...ええ、この例で十分に明確であるかどうかはわかりませんが、アイデアはここにあります。変数(たとえば、巨大なデータブロック)にデータを保存したくない場合がありますが、同じ結果を得る方法はありますか?

回答 1 件
  • I think I'm forgetting something evident but I can't seem to find a way to assign a value if it validates a condition remaining as DRY as possible

    よくある誤解を嫌うことから始めましょう。

    これは、DRYの意味の完全な不実表示です。  Customer を持っている場合  オブジェクトとあなたは Address を持っています  オブジェクトと Customer  フィールド BillingCity があります  および BillingPostalCode  および HomeCity  等々、同じ情報が2つの場所で重複して表されているため、コードはDRYではありません。コードを再設計して、 Customer   Address のコレクションがあります  オブジェクト。

    さて、ショー全体で重複したコードをカットアンドペーストするのは避けるのが賢明ですが、DRYはコードの設計に関するものです中規模から大規模。 DRYは、コードが同じ式で同じ変数を2回使用することを絶対に意味しません!

    これで問題は解決しましたので、言語に対する批評を見てみましょう。

    私たちはしばしば「表現コンテキスト」にある状況にあります。つまり、長い、おそらく流avoidなスタイルの表現であり、冗長な作業を避けたいと思っています。たとえば、次のようになります。

    x = M() > 0 ? M() : 0;
    
    

    たぶん M() を呼び出す  2回は高価であるか、多分i等ではありません。なんでも。関係ありません。ポイントは、2回呼び出す必要はないということです。

    式のコンテキストからステートメントコンテキストにドロップする必要があるのはいらいらします。

    var m = M();
    x = m > 0 ? m : 0;
    
    

    それはもちろん合法ですが、それは少し厄介です。また、トリッキーになる可能性のあるコンテキストがいくつかあります。

    N(P() ?? (M() > 0 ? M() : 0));
    
    

    今、私たちは何をしますか? M() だけを呼び出したいと仮定して、セマンティクスを長文で記述せずに保持する明白な方法はありません。   P() の場合  無効である。

    var t = default(T);
    var p = P();
    if (p == null) {
      var m = M();
      t = m > 0 ? m : 0;
    } else  {
      t = p.Value;
    }
    N(t);
    
    

    ユック。 OMGそれはとても恐ろしいです。

    他の言語は let を導入することでこの問題を解決します  式。私たちが本当に望んでいるのは、表現の途中で新しいローカルを紹介できるようにすることです。一般的な構文は let ID = EXPRESSION in EXPRESSION です  および ID  特定の意味を持つが in のスコープ内にのみある読み取り専用変数になります :

    N(P() ?? (let m = M() in m > 0 ? m : 0));
    
    

    C#する  let をサポート  式がクエリ理解でのみ。言語でより一般的にサポートされていれば素晴らしいと思います。

    let を追加するために長年にわたって多くの提案がありました  式、またはより一般的な形式である式をシーケンス化して、長年にわたってC#にします。例については、github roslyn課題トラッカーを参照してください。たぶん、これはC#8に入るでしょう。必要に応じて、フォーラムに参加してください。

    では、その間に何ができますか?

    そこに判明 C#のlet式。 let x = y in z   (((Func<X, Z>)(x=>z))(y)) を書くための単純な方法です 。だからあなたは書くことができます:

    N(P() ?? (((Func<int, int>)(m => m > 0 ? m : 0))(M())));
    
    

    しかし、それはほとんど恐ろしく見えます。それは読めない混乱です。

    問題はラムダです。これは良いでしょう:

    Func<int, int> f = m => m > 0 ? m : 0;
    ...
    N(P() ?? f(M()));
    
    

    しかし、それは少し不透明です。これをどのようにさらに改善できますか?

    ローカル関数にすることもできますが、さらに良いことには、拡張メソッドにして流なプログラミングを行うことができます。

    public static int NotNegative(this int x) => x > 0 ? x : 0;
    ...
    N( P() ?? M().NotNegative());
    
    

    できたこれは M() のみを評価します  一度だけスーパーボーナス、読みづらくなります。これは、プログラムテキストが読みにくい句読点であるのではなく、プログラムテキストが実行中の操作を表しているためです。

    少し流fluentなスタイルの拡張メソッドは、コードを読みやすくします。それらを使用する習慣を身に付けます。

あなたの答え