0

私はこのコードを得ました:

List<string> values = getValues();
Details detailsData = getDetails();

if (values[0].Equals(detailsData.Attr1))
    if (values[1].Equals(detailsData.Attr2))
        if (values[2].Equals(detailsData.Attr3))
            if (values[3].Equals(detailsData.Attr4))
                if (values[4].Equals(detailsData.Attr5))
                    return true;

getValues()オブジェクトに (^^) が存在することを望んでいる文字列リストを返しDetailsます。

上記のコードを実装するためのより効率的またはより「きれいな」方法はありますか?

編集

 class Details : MainDetails
{
    string Attr3{ get; set; }
    string Attr4{ get; set; }
    string Attr5{ get; set; }
}

 class MainDetails
{
    string Attr1{ get; set; }
    string Attr2{ get; set; }
}

ところで、MainDetails を拡張し、この検証を必要とする Details のような他のオブジェクトがいくつかある可能性があります。つまり、これはコードが複数回使用されることになります。

4

6 に答える 6

4

簡単な改善:

if (values[0].Equals(detailsData.Attr1) &&
    values[1].Equals(detailsData.Attr2) &&
    values[2].Equals(detailsData.Attr3) &&
    values[3].Equals(detailsData.Attr4) &&
    values[4].Equals(detailsData.Attr5))
{
    return true;
}

これを1か所だけで行う場合は、それ以上先に進む必要はありません。複数の場所で同じことを行う場合は、関数Detailsを別の関数に変換するなどの設定を検討しList<string>、次に例を使用してそれらを比較することを検討してくださいSequenceEquals

編集:考えれば考えるほど、文字列のフラットリストをクラスの階層内のリストと比較するのは悪い考えのように思えますが、拡張可能な方法でこれを行う方法の例を次に示します。基本クラスは上位 2 つの値を「消費」し、派生クラスに渡して残りをチェックします。

class MainDetails
{
    string Attr1 { get; set; }
    string Attr2 { get; set; }

    protected virtual bool Matches(IEnumerator<string> e)
    {
        // Check the first two items exist and match
        return
            e.MoveNext() && e.Current.Equals(Attr1) &&
            e.MoveNext() && e.Current.Equals(Attr2);
    }

    public bool Matches(IEnumerable<string> details)
    {
        using (var e = details.GetEnumerator())
        {
            // Check the details match. (Optionally check
            // that there are no "extra" details.)
            return Matches(e); // && !e.MoveNext();
        }
    }
}

class Details : MainDetails
{
    string Attr3 { get; set; }
    string Attr4 { get; set; }
    string Attr5 { get; set; }

    protected override bool Matches(IEnumerator<string> e)
    {
        // Check the MainDetails match, and the next three too.
        return base.Matches(e) &&
            e.MoveNext() && e.Current.Equals(Attr3) &&
            e.MoveNext() && e.Current.Equals(Attr4) &&
            e.MoveNext() && e.Current.Equals(Attr5);
    }
}

...

List<string> values = getValues();
Details detailsData = getDetails();

if (detailsData.Matches(values))
    return true;

あなたの正確なユースケースはわかりませんが、うまくいけば、これがあなたにいくつかのアイデアを与えるかもしれません.

于 2013-02-26T12:02:06.450 に答える
2

プロパティをすべて配列に変更できない場合は、少なくともコードをもう少しきれいに書くことができます...ただし、これは非常に主観的です!

List<string> values = getValues();
Details detailsData = getDetails();

if
(
    values[0].Equals(detailsData.Attr1) &&
    values[1].Equals(detailsData.Attr2) &&
    values[2].Equals(detailsData.Attr3) &&
    values[3].Equals(detailsData.Attr4) &&
    values[4].Equals(detailsData.Attr5)
)
{
    return true;
}
于 2013-02-26T12:02:54.660 に答える
1

使用する場所にクリーンなコードが必要な場合は、クラスにいくつかのインデクサーを配置できます。

    class Details : MainDetails
    {
        string Attr3 { get; set; }
        string Attr4 { get; set; }
        string Attr5 { get; set; }

        public override string this[int index]
        {
            get
            {
                switch (index)
                {
                    case 3:
                        return Attr3;
                    case 4:
                        return Attr4;
                    case 5:
                        return Attr5;
                }
                return base[index];
            }
        }
    }

    class MainDetails
    {
        string Attr1 { get; set; }
        string Attr2 { get; set; }

        public virtual string this[int index] 
        {
            get
            {
                switch (index)
                {
                    case 1:
                        return Attr1;
                    case 2:
                        return Attr2;
                    default:
                        throw new NotImplementedException();
                }
            }
        }
    }

このようにして、forループを使用して比較できます

for(int i = 0; i < 5; i++)
{
   if(values[i] != detailsdata[i+1])
      return false;
}
return true;

GetAtttributValue(int i);のようなクラスにメソッドを配置するだけでも、同じことが実現できます。

于 2013-02-26T12:11:15.313 に答える
0

Rawlingsの回答に加えて。Details オブジェクトをリストに変換する関数は、次のようになります。

private static IEnumerable<string> GetDetailProperties(Details details) {
    yield return details.Attr1;
    yield return details.Attr2;
    yield return details.Attr3;
    yield return details.Attr4;
    yield return details.Attr5;
}

SequenceEquals メソッドを使用して、両方のリストを比較できます。

于 2013-02-26T12:06:35.333 に答える
0

プロパティがそのように命名されている間、これを行う「より明確な」方法はありません。(2 つのコード行を節約するために) リフレクションを使用することもできますが、パフォーマンスの問題が発生します。

于 2013-02-26T12:04:18.107 に答える
0

私は次のようなことを言うでしょう

List<string> values = getValues();
Details detailsData = getDetails();

if (values.SequenceEqual(new[] { detailsData.Attr1, detailsData.Attr2, detailsData.Attr3, detailsData.Attr4, detailsData.Attr5, }))
    return true;

これはSequenceEqualLINQ の拡張メソッドを使用します。MSDN:Enumerable.SequenceEqual<TSource>を参照してください。

于 2013-02-26T12:04:24.070 に答える