96824


私は C# の初心者です。この質問は初歩的なものですが、私にとっては難しいです。

if 文を使用して条件分岐を実行しています。 しかし、ある条件下で、そのif文に含まれる処理をすべて実行したいと考えています。  
私のプログラムには if 文がたくさんありますが、これは賢い書き方とは思えません。  
「a」の記述が冗長なので、どちらかの if 文に「a」の条件を入れ忘れる可能性があります。

処理Bと処理Cを重複させずに、「a」の場合のすべての処理を実行する賢い方法はありますか？

[code]

    if (a || b)
    {
        Process B
    }
    if (a || c)
    {
        Process C
    }
    if (a || d)
    {
        Process D
    }
    
[/code]


CC BY-SA 4.0
2023-11-18T14:24:38.320
96821
2023-11-20T02:33:56.357
2023-11-20T02:33:56.357
3060
57998
question
c#
ある条件下でのみif文に含まれる処理をすべて実行したい


条件aのケースで条件bcdを判定するという意味ですか？

[code]

    if(a)
    {
        if (b)
        {
            Process B
        }
        else if (c)
        {
            Process C
        }
        else if (d)
        {
            Process D
        }
    
    }
    
[/code]

補足を受けて条件aの適合時に全てのプロセスを実行する処理を試作しました  
バージョン指定がないのでC#10.0以降を前提としています

[code]

    using System;
    using static System.Console;
    
    Random random = new Random();
    Func<Random,int> result = static rand => rand.Next(2);
    int a = result(random);
    
    (bool,Delegate) b = (result(random) > 0,(string s) => WriteLine($"{s}:ProcessA")),
    c = (result(random) > 0,(string s) => WriteLine($"{s}:ProcessB")),
    d = (result(random) > 0,(string s) => WriteLine($"{s}:ProcessC"));
    
    foreach((bool,Action<string>) p in new[]{b,c,d})
        if(p.Item1 && a > 0)
        {
            p.Item2("True");
            break;
        }
        else if(a == 0)
            p.Item2("False");
    
[/code]

以上のコードは`result(Random rand)`が0か1のいずれを返すかで条件分岐を行う手続きです  
タプル型の`(bool,Delegate)`で条件とそれに付随する処理(ラムダ式)をまとめておくことで、foreach内にて条件分岐によるプロセスの実行を管理します

例えば条件aを **int型の変数aが0のケース** と仮定すれば、この条件が成立する場合に`if(a ==
0)`へ分岐して変数bcdのラムダメソッドを全て実行します

ここでは`if(p.Item1 && a > 0)`とのプロセスの競合がないことを分かりやすく示すために **True** もしくは **False**
を文字列として受け取る引数を用意しています

条件が不成立の時は変数bcdの内最初にtrue判定となった変数のラムダメソッドだけを実行後`break`よりループを脱します

これで条件aの成立時にのみ全てのプロセスを実行するパターンを一応は構築できるかと思います


CC BY-SA 4.0
2023-11-18T23:47:26.643
96822
2023-11-19T13:45:36.973
2023-11-19T13:45:36.973
60458
60458
96821
answer


配列などのデータ構造にまとめて扱うのが良いと思います。

例:

[code]

    // 私はC#ユーザーでは無いので、これは慣用的なC#コードではないかも知れません
    
    var a = false;
    var b = true;
    var c = true;
    var d = true;
    
    // 条件（ブール値）と処理内容（関数）のタプルを要素に持つ配列
    var processes = new (bool,  Action)[] {
        (b, () => Console.WriteLine("Process B")),
        (c, () => Console.WriteLine("Process C")),
        (d, () => Console.WriteLine("Process D")),
    };
    
    
    if (a) {
        // 全ての処理を実行
        // 条件部は利用しないので「_」で捨てる
        foreach (var (_, func) in processes) {
            func();
        }
    } else {
        // 条件部が真である処理を実行する
        foreach (var (cond, func) in processes) {
            if (cond) {
                func();
            }
        }
    }
    
[/code]


CC BY-SA 4.0
2023-11-19T01:55:35.093
96824
2023-11-19T13:35:33.717
2023-11-19T13:35:33.717
3054
3054
96821
answer


> 「a」の記述が冗長なので、どちらかの if 文に「a」の条件を入れ忘れる可能性があります。

解決すべき課題が何なのかいまいちわからないのですが，  
問題視しているのが「冗長さ」ではなくて「書き忘れる可能性」なのだということであれば……

[code]

    //各処理を　使う情報を引数に取る　メソッドにする．
    void ProcessB( bool a, bool b ){ ... }
    void ProcessC( bool a, bool c ){ ... }
    void ProcessD( bool a, bool d ){ ... }
    
    //呼ぶ側
    void SomeFunc()
    {
      //必ず引数を２つ指定しないとコンパイル通らないから「書き忘れ」は無い．
      //（「書き間違い」ならばあり得るだろうけども）
      ProcessB( a, b );
      ProcessC( a, c );
      ProcessD( a, d );
    }
    
[/code]

のように，明示的に「 `a` と `b` を引数とするメソッド」といった形に書けばどうですか？  
さすがにこの状態で `{...}` の箇所の実装時に「`a` の存在を忘れて（というか無視して） `b`
だけ使うコードを書いちゃう」ということはそうそう無いのではないか，と思います．


CC BY-SA 4.0
2023-11-20T01:47:12.017
96841
2023-11-20T01:47:12.017
52236
96821
answer