6

リストに値を挿入する前に、いくつかのチェックを実行できる関数をコーディングしたいと思います。例えば:

class Person {
    public string Name { get; set; }
    public int Value { get; set; }
    public Guid Id { get; set; }
}
-------
var persons = new List<Person>();
// add a new person if John doesn't exist
persons.AddIf(s => !s.Name.Equals("John"), new Person { ... });
----
public static void AddIf(this List<T> lst, Func<T, bool> check, T data)
{
     // how can I use the Func 'check' to check if exist an object with the
     // information that the client wrote and, if not exists, insert the new value
     // into the list???
     if ( check )
}

Func'check'を使用して、クライアントが書き込んだ情報を持つオブジェクトが存在するかどうかを確認し、存在しない場合は新しい値をリストに挿入するにはどうすればよいですか?

4

3 に答える 3

11

メソッドをジェネリックにする必要があります。

public static void AddIf<T>(this List<T> lst, Func<T, bool> check, T data)
{
    if (!lst.All(check))
        return;

    lst.Add(data);
}

そして、あなたが望むような使用法(すべてのアイテムが述語を満たす必要があります):

persons.AddIf(s => !s.Name.Equals("John"), new Person { ... });
于 2012-11-14T06:42:43.697 に答える
0

上記の回答からの迅速な組み合わせ/変更、いくつかのコメント:(私の担当者は低すぎて単に赤面をコメントすることはできません)

したがって、質問の例の特定の詳細に基づいて:

Func 'check' を使用して、クライアントが書き込んだ情報を含むオブジェクトが存在するかどうかを確認し、存在しない場合は新しい値をリストに挿入するにはどうすればよいですか?

1)リストに追加する前に(「チェック」を開くのではなく)、特に重複をチェックするための汎用拡張機能を作成/使用することを検討します(前述のように、一般的な操作です)。

public static void AddIfDistinct<T>(this List<T> lst, T data, Func<T, bool> dupeCheck)
{
    if (lst.Any(dupeCheck))
        return;

    lst.Add(data);
}

2)要件に基づいて、私の意見では、「すべて」よりも「すべて」よりも「任意」の方が意味的にはるかに明確です-現在の「すべて」のアイテムが重複していないことを確認するのではなく、「任意」の重複を確認しています. . 些細なことに聞こえるかもしれませんが、すぐにわかると言っても過言ではないと思います。これは明らかに、渡すラムダが次のようになることを意味します (ここでのセマンティクスの変更は、適切な名前の拡張メソッドを実際に取得する必要があることを意味します)。

s => s.Name.Equals("John")

3) 最後のコメント、適切であれば、「CompareTo」などのクラスの一部をオーバーライドして、本当に汎用的な「AddToListIfUnique」などを作成することもできます。

また、例で Expression< Func<...>> を使用しても、(誰かが示唆したように) まったく役に立ちません。とにかく List を使用しているためです (IQueryable などを使用している場合にのみ価値があります)。

于 2013-01-17T10:02:21.427 に答える
0

独自のセマンティクスについては、信頼できる答えが既にあります。しかし、私にとって、メソッドの命名は、考えれば考えるほどわかりにくくなります。AddIfある場合は追加するか、すべての場合は追加することを意味しますか? あなたの場合、それがすべてです。したがって、より適切な名前を付ける必要があります。AddIfAllか何か。

何かが存在しない場合にリストに追加することは一般的な要件であり、私が提案するのは、呼び出し側から簡単にする目的のためにもう少し肉付けされたものです(私は信じています)。

多分

public static bool AddIfNotContains<S, T>(this ICollection<S> lstObject, 
                                          Func<S, T> selector, T valueToMatch,
                                          S objectToAdd)
{
    if (lstObject.Contains(selector, valueToMatch))
        return false;

    lstObject.Add(objectToAdd);
    return true;
}

Containsプログラムで使用することを好む小さなオーバーロード:

public static bool Contains<S, T>(this IEnumerable<S> lstObject, 
                                  Func<S, T> comparer, T valueToMatch)
{
    return lstObject.Any(s => comparer(s).Equals(valueToMatch));
}

Equalsこれにより、毎回オペレーターを作成する手間が省けます。

あなたは呼び出すことができます:

persons.AddIfNotContains(s => s.Name, "John", new Person { ... });

これにより、構文がはるかに簡単になると思います。

ノート:

ここで問題を認識していただければ幸いです。とても上手に書けます

persons.AddIfNotContains(s => s.Name, "John", new Person { Name = "Serena", .. });

Serenaここでは をチェックしているため、その名前の誰かがすでに存在する場合でもJohn。それがあなたにとって大丈夫なら、まあまあです。あなたの問題を正しく理解していれば、より良い実装は次のようになります

public static bool AddIfTrulyNotContains<S, T>(this ICollection<S> lstObject, 
                                               Func<S, T> selector, S objectToAdd)
{
    if (lstObject.Contains(selector, selector(objectToAdd)))
        return false;

    lstObject.Add(objectToAdd);
    return true;
}

これで簡単に呼び出すことができます:

persons.AddIfTrulyNotContains(s => s.Name, new Person { Name = "John", .. });

これは、リストにない場合にチェックしJohnて追加するだけです。さらに、加算を表すJohn戻り値の型を にしました。bool

于 2012-11-14T13:24:05.723 に答える