5

私は今、次のものを持っています:

switch (Mysort)
{
    case "reqDate":
        lstDMV.Sort((x, y) => DateTime.Compare(x.RequestDate, y.RequestDate));
        break;
    case "notifDate":
        lstDMV.Sort((x, y) => DateTime.Compare(x.NotifDate, y.NotifDate));
        break;
    case "dueDate":
        lstDMV.Sort((x, y) => String.Compare(x.TargetDateShort, y.TargetDateShort));
        break;
    case "days":
        lstDMV.Sort((x, y) => x.DaysLapsed.CompareTo(y.DaysLapsed));
        break;
}

ケースステートメントを取り除き、次のようなことをしたいだけです:

lstDMV.Sort((x, y) => String.Compare(x.MySort, y.MySort));

case ステートメントは非常に大きく、読みやすさが大幅に低下します。しかし、MySort含まれlstDMVていないため、機能していません。それを代用できる別の方法はありますか?

MySortもちろん、変数の値がlstDMVプロパティ名と正確に一致するようにテキストを変更します。

私はまた、運が悪かったので次のことを試しました:(

 if (sort != "")
            {
                string xsort, ysort;
                xsort = "x." + sort;
                ysort = "y." + sort;

                lstDMV.Sort((x, y) => String.Compare(xsort, ysort));
            }
4

5 に答える 5

2

すべてのプロパティ タイプが実装されていると仮定すると、リフレクションを使用できますIComparable

private class Test
{
    public DateTime RequestDate { get; set; }

    public string Name { get; set; }
}

private static void Main(string[] args)
{
    var list = new List<Test>
    {
        new Test
        {
            RequestDate = new DateTime(2012, 1, 1),
            Name = "test"
        },
        new Test
        {
            RequestDate = new DateTime(2013, 1, 1),
            Name = "a_test"
        },
    };

    string mySort = "RequestDate";
    list.Sort((x, y) =>
        {
            // Gets the property that match the name of the variable
            var prop = typeof(Test).GetProperty(mySort);

            var leftVal = (IComparable)prop.GetValue(x, null);
            var rightVal = (IComparable)prop.GetValue(y, null);

            return leftVal.CompareTo(rightVal);
        });

    Console.Read();
}

コードが少なくても、switch現在のコードよりも読みにくいため、お勧めしません。

于 2013-01-18T16:35:30.590 に答える
2

比較関数 Func の辞書

    public class YourDataClass {
        public string RequestDate { get; set; }
        public string NotifDate { get; set; }
        .
        .
        .
    }

    public class Sorter<T> where T : YourDataClass {
        private Dictionary<string, Func<T, T, int>> actions =
            new Dictionary<string, Func<T, T, int>> {
                {"reqDate", (x, y) => String.Compare(x.RequestDate, y.RequestDate)},
                {"notifDate", (x, y) => String.Compare(x.NotifDate, y.NotifDate)}
            };

        public IEnumerable<T> Sort(IEnumerable<T> list, string howTo) {
            var items = list.ToArray();
            Array.Sort(items, (x, y) => actions[howTo](x, y));
            return items;
        }
    }

    public void Sample() {
        var list = new List<YourDataClass>();
        var sorter = new Sorter<YourDataClass>();
        var sortedItems = sorter.Sort(list, "reqDate");
    }
于 2013-01-18T16:38:13.870 に答える
1

Linq と Reflection を組み合わせて、3 行のコードで問題を解決します。概念実証は次のとおりです。

public class Test
{
    public string Name;
    public int Age;
    public DateTime Since;
}

void Main()
{
    var tests = new Test[] {
        new Test(){Name="Dude", Age=23, Since = new DateTime(2000,2,3)},
        new Test(){Name="Guy", Age=29, Since = new DateTime(1999,3,4)},
        new Test(){Name="Man", Age=34, Since = new DateTime(2008,11,5)},
        new Test(){Name="Gentleman", Age=40, Since = new DateTime(2006,7,6)}
    };

    //up until here, all code was just test preparation. 
    //Here's the actual problem solving:

    string fieldToOrderBy = "Since"; //just replace this to change order
    FieldInfo myf = typeof(Test).GetField(fieldToOrderBy);
    tests.OrderBy(t=>myf.GetValue(t)).Dump(); 

    //the Dump() is because I ran this in LinqPad. 
    //Replace it by your favaorite way of inspecting an IEnumerable
}

パフォーマンスを向上させるために、並べ替えの前にフィールド情報が取得されることに注意してください。

「SortBy」文字列がフィールド名ではないことは理解していますが、それは問題の簡単な部分であり、辞書を使用して SortBy 文字列を FieldName にマップすることで解決できます。

于 2013-01-18T16:35:41.123 に答える
0

とが type であると仮定するxと、マッピングを辞書に保存できます。yA

var sortingFuncs = new Dictionary<string, Func<A, A, int>>();

並べ替えメソッドの呼び出しには、switchこれ以上は必要ありません。

lstDMV.Sort(sortingFuncs[Mysort]);

ただし、ある時点でディクショナリにデータを入力する必要があるため、他の場所にほぼ同じ量のコードが作成されることに注意してください。利点は、このプロセスがより動的になる可能性があることです。たとえば、プラグインに独自のソート キーと比較関数を追加させることができます。

一方で、コンパイラーが適格な値に基づいて選択コードを最適化できない可能性があるため、パフォーマンスがわずかに低下する可能性がありますMysort

于 2013-01-18T16:38:01.623 に答える
0

プロパティ セレクターを作成します。

Func<T, object> CreatePropSelector<T>(string propertyName)
{
    var parameter = Expression.Parameter(typeof(T));
    var body = Expression.Convert(Expression.PropertyOrField(parameter, propertyName), typeof(object));
    return Expression.Lambda<Func<T, object>>(body, parameter).Compile();
}

それを使用して、プロパティ名でシーケンスを並べ替えます。

lstDMV.OrderBy(CreatePropSelector<YourObjectType>(Mysort))

他の Linq メソッドと同様に、リストは並べ替えられませんが、列挙子が作成されます。

Mysort = "RequestDate";
foreach(var item in lstDMV.OrderBy(CreatePropSelector<YourObjectType>(Mysort)))
     // sequence ordered by RequestDate property
于 2013-01-18T16:40:17.590 に答える