Extension Method, Func of T and List T

I would like to encode a function that can do some validation before inserting a value into a list. For instance:

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 ) } 

How can I use Func 'check' to check if an object exists with the information that the client wrote, and if it does not exist, insert a new value into the list?

+6
source share
3 answers

You need to make your method general.

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

And use as you like (all elements must satisfy the predicate):

 persons.AddIf(s => !s.Name.Equals("John"), new Person { ... }); 
+11
source

For your own semantics, you have an answer to rely on. But for me, the naming method is misleading, the more I think about it. AddIf means add, if any, or add if all? In your case, that's all. Therefore, you should name it better. AddIfAll or something like that.

To add to the list, if something does not exist, this is a general requirement, and what I would like to offer is something even more complex (I think) for your purpose, which makes it easier for the subscriber.

May be

 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; } 

A little Contains overload, which I prefer to use in my programs:

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

This allows us to avoid problems with recording the Equals statement from our side each time.

You may call:

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

I think the syntax is much simpler.

Note:

I hope you know about that. You can write very well

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

, even if someone already exists with the name Serena , because here you check John . If it is good for you, good and good. The best implementation, if I understand your problem correctly, would be :

 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; } 

Now you can easily call:

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

This simply checks John and adds if John is not on the list. In addition, I made a return type for bool to indicate the addition.

0
source

Quick combination / change of answers above, with some comments: (my representative is too low to just comment on the blush)

So, based on some details in the example question:

How can I use Func 'check' to check if an object exists with the information that the client wrote, and if it does not exist, insert a new value into the list?

1) I would definitely think about creating / using a common extension specifically designed to check for duplicates (as mentioned, a common operation) before adding to the list (and not with open "check"), so there might be something like this:

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

2) on the basis of the requirement "Any" is much clearer, semantically, than "Everything", in my opinion, we check "any" duplicates, and do not check that "all" current elements are "not", duplicated ... It may seem trivial, but I think it’s safe to say that this is more obvious. This obviously means that the lambda you're going through with will look like this (changing semantics here means that you really need to use the extension method correctly)

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

3) the last comment, if appropriate, you can also override some things in your class, for example, CompareTo, etc., and create a really generic AddToListIfUnique, etc.

Also, using the Expression <Func <... β†’ expression in your example would not help at all (as someone suggested), since you are still using List (it would be useful if you were using IQueryable, etc.)

0
source

All Articles