3

誰でも私に提案してもらえますか、Swichケースまたはその他を使用して以下のコードを記述するより良い方法はありますか?

    from p in l_list
    where ((LicenceType == "Full" && SystemType == "Single") && p.ProductName != "Full DoubleProduct ")
       || ((LicenceType == "Full" && SystemType == "Multiple") && p.ProductName != "Full SingleProduct")
       || ((LicenceType == "Partial" && SystemType == "Single") && p.ProductName != "Locked DoubleProduct") 
       || ((LicenceType == "Partial" && SystemSize == "Multiple") && p.ProductName != "Locked SingleProduct")
       || ((LicenceType == "Locked" && SystemSize == "Single") && p.ProductName != "Locked DoubleProduct") 
       || ((LicenceType == "Locked" && SystemType == "Multiple") && p.ProductName != "Locked SingleProduct")
4

5 に答える 5

6

その巨大なブール条件は、データオブジェクトのサブセット間で共有されるいくつかの一般的な品質を表しています。その品質を正確に特定し、わかりやすい名前を付けます。

次に、データオブジェクトのプロパティを介してその数量の値を公開するか、同じことを行う拡張メソッドを記述します。最後に、既存の条件をこのアクセサーを使用して置き換えます。

たとえば、品質の名前が「親しみやすさ」の場合、次のようになります。

where model.IsFriendly // property

またはこれ:

where model.IsFriendly() // extension method BusinessRules.IsFriendly(Model m)
于 2013-02-15T13:19:27.453 に答える
4

ライセンスの種類を「因数分解」し、条件がより単純になることを観察することで、表現を単純化できるようです。

(
(SystemType == "Single"   && p.ProductName != "DoubleProduct") ||
(SystemType == "Multiple" && p.ProductName != "SingleProduct")
) &&
(
LicenceType == "Full"  ||
LicenceType == "Partial" ||
LicenceType == "NotApplicable"
)

"Full""Partial"、および以外のライセンス タイプがない場合は"NotApplicable"、最終条件の 2 番目の句を破棄できます。

(SystemType == "Single"   && p.ProductName != "DoubleProduct") ||
(SystemType == "Multiple" && p.ProductName != "SingleProduct")

編集:一般に、そのような複雑なマルチパート条件がある場合、できる最善のことは、共通のサブ式を抽出して、条件の数を減らそうとすることです。基本的な問題は、複数の次元を持つ条件を「線形」なコードで表現しようとしていることです。この「折りたたみ」により、コードが読みにくくなります。

この問題を回避する 1 つの方法は、次のように条件をテーブルに「エンコード」することです。

var conditions = new[] {
    new[] { "Full",          "Single",   "Full DoubleProduct"    }
,   new[] { "Full",          "Multiple", "Full SingleProduct"    }
,   new[] { "Partial",       "Single",   "Locked DoubleProduct"  }
,   new[] { "Partial",       "Multiple", "Locked SingleProduct"  }
,   new[] { "NotApplicable", "Single",    "Locked DoubleProduct" }
,   new[] { "NotApplicable", "Multiple", "Locked SingleProduct"  }
};

これで、次のような状態で使用できます。

Where (p => conditions.Any(cond =>
    cond[0] == p.LicenceType
 && cond[1] == p.SystemType
 && cond[2] != p.ProductName
))

このアプローチの利点は、プログラムの読者のために条件が「表」にされ、新しい行を追加するだけで簡単に拡張できることです。IQueryable欠点は、部分的な結果をメモリに取り込まずに、ソースに対してそのようなクエリを実行できなくなったことです。

于 2013-02-15T13:21:29.897 に答える
0

条件を配列(状態マトリックス)として「コーディング」してから、foreach/forおよびflagsを使用できます。

別の可能な解決策はbash.dすでに-ビットフィールドを使用することによって与えられました。本当に必要な場合は、両方をさらに組み合わせることができます。

私自身は、繰り返しの文字列( "Full"など)を使用するのではなく、間違いを避けて読みやすくするために(場合によっては)定数に入れます。

また、オペランドの優先度が同じ場合、たとえば角かっこは必要ない場合は、角かっこを使用する必要はあり(a == b && c == d) && e == fません。

そして最後に、大事なことを言い忘れましたが、ロジックを逆にすることを試みることができます。これにより、たとえば、条件が単純化される可能性があり(a || b || c) = !(!a && !b && !c)ます。これは、考えられる条件の既知のサブセットを処理している場合に特に役立ちます。その後、それを「最適化」できます。

于 2013-02-15T13:53:24.703 に答える
0

フラグを使用して、オブジェクトまたは属性の値を示すことができます。

[Flags]
enum MyEnum
{
    val1 = 0x01,
    val2 = 0x02,
    val3 = 0x04
}

ビット演算子(&&、||)を使用して、値を確認できます。ここを参照してください。

于 2013-02-15T13:20:25.923 に答える
0

Linqでは、外部関数を呼び出すことができます。では、「ビジネスロジック」をクエリから外してみませんか?つまり、メソッドを作成できます

bool IsLincensedForXXX(Product p)

LINQ式で使用します。

from p in l_list where IsLincensedForXXX(p)

よりクリーンで、維持しやすく、再利用しやすいと思います。

于 2013-02-15T15:01:24.367 に答える