Find an object within a list and replace its value - c#

I have the following list and class:
List<MyClass> MyList
public class MyClass
{
public int id { get; set; }
public bool checked { get; set; }
}
I also have the two variables:
int idToFind = 1234;
bool newcheckedvalue = true;
What I need to do is search the list and find the MyClass object where the id equals that value of idToFind. Once I have the object in the list, I then want to change the value of the checked property in the class to that of the newcheckedvalue value.
LINQ seems to be the solution to this problem, I just can't get the expression right. Can I do this in a single LINQ expression?

LINQ is for querying collection, not for modification. You can find the object like:
var item = MyList.FirstOrDefault(r=> r.id == idtoFind && r.checked == newcheckedvalue);
To find the item based on the ID only you can do:
var item = MyList.FirstOrDefault(r=> r.id == idtoFind);
Later you can set/modify its property.
//Make sure to check against Null, as if item is not found FirstOrDefault will return null
item.checked = newcheckedvalue; //or any other value

Example (to be noted that MyClass type has to be a class, a reference type, in this example):
var found = MyList.Where(ml=>ml.Id == 1234);
foreach(var f in found)
f.checked = newcheckedvalue;

Related

C# how to return 1 row from List<T> object passed as parameter

I need to return one row of List from my function Selectus.
So I pass to the function Selectus object that reflects database table fields and I need to return one row which match the parameter looking_for:
public static List<T> Selectus<T>(string looking_for)
{
//all select data
var db = OrmLiteBaza().Open();//opening database
var select_all_list = db.Select<T>();//getting all data for <T> object works fine
db.Dispose();
//try to select one row - here I have trouble:
var prop = typeof(T).GetProperties();//properties of passed <T> object
var list_selected_record = from records in select_all_list where prop[1].Name == looking_for select records;//tryin to select one record from <T> object as in looking_for variable
return list_selected_record.ToList();//here one record should be returned
}
I do not know how to select one row from the list assuming that T parameter is vary. In SelectusT> method I want to pass as T different objects which reflect fields in database table rather than creatinig separate methods for each select. e.g. call Selectus, where object passed is public class ProductCodes { public int ID { get; set; } public string SapIndex { get; set; } public string SapName { get; set; } }. Then I want to call another Selectus<ProductTypes> for another table etc... So I want to write generic/overall method and use it universally for all types of my objects which reflects the fields of few database tables. The SapIndex property is always in the same place of all objects...
Using prop[1] is incredibly fragile. Who says that the property you're currently interested in is always going to be in second place? What if someone adds another property tomorrow? What if not every T that you use have the same property in the second place on its list of properties? It is quite unclear what your actual goal is here and why you've taken the reflection route.
You would be better off using inheritance or interface implementation here. I'm going to use an interface in this answer, but either would work.
For the sake of clarity, let's assume there is a Code field in all your possible lists, and this is the property you're trying to match with.
Define a reusable interface:
public interface ICodeEntity
{
string Code { get; }
}
Apply your interface to all of the classes that you intend to use for your Selectus method.
public class Person : ICodeEntity
{
public string Code { get; set; }
// And other properties
}
public class Document : ICodeEntity
{
public string Code { get; set; }
// And other properties
}
Add a generic type constraint that limits the use of T only to types that implement your interface.
public static List<T> Selectus<T>(string code)
where T : ICodeEntity
You can now write your code in a way that it relies on the type in question having a Code property, and the compiler will help enforce it.
var db = OrmLiteBaza().Open();
var list = db.Select<T>().ToList();
db.Dispose();
return list.Where(item => item.Code == code).ToList();
Usage examples:
List<Person> peopleWithCodeABC = Selectus<Person>("ABC");
List<Person> documentsWithCodeXYZ = Selectus<Document>("XYZ");
// This will fail if Animal does not implement ICodeEntity
var compilerError = Selectus<Animal>("ABC");
I might not understand fully what you want, but instead of string looking_for you could pass in a Func<,> delegate which acts as a selector.
Something like:
public static List<TField> Selectus<T, TField>(Func<T, TField> selector)
{
var db = OrmLiteBaza().Open();
var select_all_list = db.Select<T>();
db.Dispose();
var list_selected_record = select_all_list.Select(selector); // 'using System.Linq;'
return list_selected_record.ToList();
}
Then I believe it could be called like this:
var list_one = Selectus((ProductCodes x) => x.SapIndex);
var list_two = Selectus((ProductTypes x) => x.SapIndex);
var list_three = Selectus((ProductCodes x) => x.SapName);
With this syntax I leave out the <ProductCodes, string> generic arguments to the method since they can be inferred.
Hmm, maybe you want it in the opposite dimension. You could do:
public static List<T> Selectus<T>(Func<T, bool> predicate)
{
var db = OrmLiteBaza().Open();
var select_all_list = db.Select<T>();
db.Dispose();
var list_selected_record = select_all_list.Where(predicate); // 'using System.Linq;'
return list_selected_record.ToList();
}
with:
var list_one = Selectus((ProductCodes x) => x.SapIndex == "ABC");
var list_two = Selectus((ProductTypes x) => x.SapIndex == "ABC");
var list_three = Selectus((ProductCodes x) => x.SapName == "DaName");
or:
var list_one = Selectus<ProductCodes>(x => x.SapIndex == "ABC");
var list_two = Selectus<ProductTypes>(x => x.SapIndex == "ABC");
var list_three = Selectus<ProductCodes>(x => x.SapName == "DaName");
But if it is going to always be the "same" property, like always x.SapIndex (but for different types of x), then Flater's answer looks good.
Otherwise, if you insist, your reflection approach should be possible. Use propety's name, not its index! Let me try:
public static List<T> Selectus<T>(string looking_for)
{
var db = OrmLiteBaza().Open();
var select_all_list = db.Select<T>();
db.Dispose();
const string prop_name = "SapIndex";
var prop = typeof(T).GetProperty(prop_name); // can blow up for bad T
var list_selected_record = select_all_list
.Where(x => (string)(prop.GetValue(x)) == looking_for); // 'using System.Linq;'
return list_selected_record.ToList();
}
with:
var list_one = Selectus<ProductCodes>("ABC");
var list_two = Selectus<ProductTypes>("ABC");
you can change code to return just one element
public static T Selectus<T>(string looking_for)
{
//all select data
var db = OrmLiteBaza().Open();//opening database
var select_all_list = db.Select<T>();//getting all data for <T> object works fine
db.Dispose();
//try to select one row - here I have trouble:
var prop = typeof(T).GetProperties();//properties of passed <T> object
var list_selected_record = from records in select_all_list where prop[1].Name == looking_for select records;//tryin to select one record from <T> object as in looking_for variable
return list_selected_record.FirstOrDefault();//here one record should be returned
}

Find object from collection of object

I have a class
public class ABC
{
public int Id { get; set; }
public string Name { get; set; }
public Enum Msg { get; set; }
}
and collection of this class and single object
List<ABC> objColl = new List<ABC>();
ABC obj = new ABC();
Assume collection have items and i am trying to find single object which already exists in collection.
i want to find a single object inside that collection whether it exists or not.
I had already tried
var res = objColl.contains(obj);
it always return false. i dont want compare each property of object or loop.
Use Any with your criteria:
bool res = objColl.Any(s => s.Id == obj.Id);
if you want to use Contains then override Equals().
When you call Contains(), it searches for an item in the collection that is equal to the argument you've provided. Since you have not overridden Equals(), it uses the default implementation.
You have two options:
Override Equals() in class ABC to specify checking only the properties you want to check;
Use LINQ: objColl.Any(e => e.[some property] == obj.[some property])
You can use FirstOrDefault()
Returns the first element of a sequence, or a default value if no
element is found.
var res = objColl.FirstOrDefault(x => x.Id == obj.Id);
var res = objColl.Where(s=>s.Id == obj.Id).Any();

Using LINQ. With two different lists. How can I identify objects that do not match

I have three classes:
public partial class Objective{
public Objective() {
this.ObjectiveDetails = new List<ObjectiveDetail>();
}
public int ObjectiveId { get; set; }
public int Number { get; set; }
public virtual ICollection<ObjectiveDetail> ObjectiveDetails { get; set; }
}
public partial class ObjectiveDetail {
public ObjectiveDetail() {
this.SubTopics = new List<SubTopic>();
}
public int ObjectiveDetailId { get; set; }
public int Number { get; set; }
public string Text { get; set; }
public virtual ICollection<SubTopic> SubTopics { get; set; }
}
public partial class SubTopic {
public int SubTopicId { get; set; }
public string Name { get; set; }
}
I have two lists:
IList<ObjectiveDetail> oldObj;
IList<ObjectiveDetail> newObj;
The following LINQ gives me a new list of ObjectiveDetail objects where: the Number or the Text fields for any ObjectiveDetail object in the list differ between oldObj and newObj.
IList<ObjectiveDetail> upd = newObj
.Where(wb => oldObj
.Any(db => (db.ObjectiveDetailId == wb.ObjectiveDetailId) &&
(db.Number != wb.Number || !db.Text.Equals(wb.Text))))
.ToList();
How can I modify this so the LINQ gives me a new list of ObjectiveDetail objects where: the Number or the Text fields or the SubTopic collections for any ObjectiveDetail object in the list differ between oldObj and newObj.
In other words I want an ObjectiveDetail to be added to the upd list if:
It has Text in oldObj that's different from Text in newObj
It has a Number in oldObj that's different from the Number in newObj
It has a SubTopics collection with three elements in oldObj and 4 elements in newObj
It has a SubTopics collection with no elements in oldObj and 2 elements in newObj
It has a SubTopics collection with 2 elements in oldObj and no elements in newObj
It has a SubTopics collection with elements with SubTopicId of 1 and 2 in oldObj and 1 and 3 in newObj
I hope someone can come up with just some additional line in the LINQ statement that I already have.
Instead of creating a huge and hard maintanable LINQ query that will try to find differences, I would create a list of the same objects within both list (intersection) and as a result, take sum of both collection except this intersection. To compare objects you can use IEqualityComparer<> implementation. Here is a draft:
public class ObjectiveDetailEqualityComparer : IEqualityComparer<ObjectiveDetail>
{
public bool Equals(ObjectiveDetail x, ObjectiveDetail y)
{
// implemenation
}
public int GetHashCode(ObjectiveDetail obj)
{
// implementation
}
}
and then simply:
var comparer = new ObjectiveDetailEqualityComparer();
var common = oldObj.Intersect(newObj, comparer);
var differs = oldObj.Concat(newObj).Except(common, comparer);
This will be much easier to maintain when classes change (new properties etc.).
This should be what you need:
IList<ObjectiveDetail> upd = newObj.Where(wb =>
oldObj.Any(db =>
(db.ObjectiveDetailId == wb.ObjectiveDetailId) &&
(db.Number != wb.Number || !db.Text.Equals(wb.Text)
|| db.SubTopics.Count != wb.SubTopics.Count
|| !db.SubTopics.All(ds => wb.SubTopics.Any(ws =>
ws.SubTopicId == ds.SubTopicId))
))).ToList();
How It Works
db.SubTopics.Count != wb.SubTopics.Count confirms that the new object being compared (wb) and the old object being compared (db) have the same number of SubTopics. That part is pretty straightforward.
!db.SubTopics.All(ds => wb.SubTopics.Any(ws => ws.SubTopicId == ds.SubTopicId)) is a bit more complicated. The All() method returns true if the given expression is true for all members of the set. The Any() method returns true if the given expression is true for any member of the set. Therefore the entire expression checks that for every SubTopic ds in the old object db there is a Subtopic ws with the same ID in the new object wb.
Basically, the second line ensures that every SubTopic present in the old object is also present in the new object. The first line ensures that the old & new objects have the same number of SubTopics; otherwise the second line would consider an old object with SubTopics 1 & 2 the same as a new object with SubTopics 1, 2, & 3.
Caveats
This addition will not check whether the SubTopics have the same Name; if you need to check that as well, change the ws.SubTopicId == ds.SubTopicId in the second line to ws.SubTopicId == ds.SubTopicId && ws.Name.Equals(ds.Name).
This addition will not work properly if an ObjectiveDetail can contain more than one SubTopic with the same SubTopicId (that is, if SubTopicIds are not unique). If that's the case, you need to replace the second line with !db.SubTopics.All(ds => db.SubTopics.Count(ds2 => ds2.SubTopicId == ds.SubTopicId) == wb.SubTopics.Count(ws => ws.SubTopicId == ds.SubTopicId)). That will check that each SubTopicId appears exactly as many times in the new object as it does in the old object.
This addition will not check whether the SubTopics in the new object & the old object are in the same order. For that you would need to replace the 2nd line with db.SubTopics.Where((ds, i) => ds.SubTopicId == wb.SubTopics[i].SubTopicId).Count != db.SubTopics.Count. Note that this version also handles non-unique SubTopicId values. It confirms that the number of SubTopics in the old object such that the SubTopic in the same position in the new object is the same equals the total number of SubTopics in the old object (that is, that for every SubTopic in the old object, the SubTopic in the same position in the new object is the same).
High Level Thoughts
Konrad Kokosa's answer is better from a maintainability perspective (I've already upvoted it). I would only use a big ugly LINQ statement like this if you don't expect to need to revisit the statement very often. If you think the way you decide whether two ObjectiveDetail objects are equal might change, or the method that uses this statement might need to be reworked, or the method is critical enough that someone new to the code looking at it for the first time needs to be able to understand it quickly, then don't use a big long blob of LINQ.
Normally I would go with #Konrad Kokosa way. But it looks like you need a fast solution.
I tried it with some data. It gives the expected result. I am sure that you can modify the code for desired results.
var updatedObjects = oldObj.Join(newObj,
x => x.ObjectiveDetailId,
y => y.ObjectiveDetailId,
(x, y) => new
{
UpdatedObject = y,
IsUpdated = !x.Text.Equals(y.Text) || x.Number != y.Number //put here some more conditions
})
.Where(x => x.IsUpdated)
.Select(x => x.UpdatedObject);
Problems
Your LINQ query was not that bad but some proplems needed to be solved:
Using .Any() in a .Where() means that the query is much slower than needed. This is because for every item in objNew, you iterate the items of objOld.
!db.Text.Equals(wb.Text) throws an exception when db.Text is null.
Your code doesn't detect new items added to objNew that doesn't exists in objOld. I don't know if that is a problem because you didn't told us if that is possible.
Solution
If you compare collections, it would be a good idea to override the Equals() and GetHashcode() methods:
public partial class ObjectiveDetail
{
public ObjectiveDetail()
{
this.SubTopics = new List<SubTopic>();
}
public int ObjectiveDetailId { get; set; }
public int Number { get; set; }
public string Text { get; set; }
public virtual ICollection<SubTopic> SubTopics { get; set; }
public override bool Equals(Object obj)
{
var typedObj = obj as ObjectiveDetail;
return Equals(typedObj);
}
public bool Equals(ObjectiveDetail obj)
{
if ((object)obj == null) return false;
return ObjectiveDetailId == obj.ObjectiveDetailId &&
Number == obj.Number &&
Text == obj.Text &&
SubTopics != null && obj.SubTopics != null && // Just in the unlikely case the list is set to null
SubTopics.Count == obj.SubTopics.Count;
}
public override int GetHashCode()
{
return new { A = ObjectiveDetailId, B = Number, C = Text }.GetHashCode();
}
}
Then it is easy:
var dictionary = oldObj.ToDictionary(o => o.ObjectiveDetailId);
IList<ObjectiveDetail> upd = newObj
.Where(n => !EqualsOld(n, dictionary))
.ToList();
using this method:
private bool EqualsOld(ObjectiveDetail newItem, Dictionary<int, ObjectiveDetail> dictionary)
{
ObjectiveDetail oldItem;
var found = dictionary.TryGetValue(newItem.ObjectiveDetailId, out oldItem);
if (!found) return false; // This item was added to the new list
return oldItem.Equals(newItem);
}
If I get it right, you want to make a deep comparison between two .NET objects, regardless of LINQ. Why don't you use something like comparenetobjects?
Trying to implement a deep comparison through LINQ would probably be slower and more complex than making the comparison in the memory. Even if you chose to do it in LINQ realm, you would finally retrieve the whole object and perhaps you would do it with more than one queries, adding performance overhead. Therefore, I would suggest to eagerly load your data object from database and make the deep comparison without a specific linq query.
Hope I helped!
Find the entities that are not updated then exclude:
IEnumerable<ObjectiveDetail> newOds = ...;
IEnumerable<ObjectiveDetail> oldOds = ...;
// build collection of exclusions
// start with ObjectiveDetail entities that have the same properties
var propertiesMatched = oldOds.Join( newOds,
o => new { o.ObjectiveDetailId, o.Number, o.Text },
n => new { n.ObjectiveDetailId, n.Number, n.Text },
( o, n ) => new { Old = o, New = n } );
// take entities that matched properties and test for same collection
// of SubTopic entities
var subTopicsMatched = propertiesMatched.Where( g =>
// first check SubTopic count
g.Old.SubTopics.Count == g.New.SubTopics.Count &&
// match
g.New.SubTopics.Select( nst => nst.SubTopicId )
.Intersect( g.Old.SubTopics.Select( ost => ost.SubTopicId ) )
.Count() == g.Old.SubTopics.Count )
// select new ObjectiveDetail entities
.Select( g => g.New );
// updated ObjectiveDetail entities are those not found
// in subTopicsMatched
var upd = newOds.Except( subTopicsMatched );
This would work w/ EF and run completely server-side if newOds and oldOds are IQueryable<ObjectiveDetail>s from a DbContext
I have tried what you wanted but it is not too "neat" and it was not possible for me to make "one-liner-linq-expression" type code. Check it out and see if it is acceptable to you.
Also you need to check the performance but as you said there are not many objects so performance might not be of concern.
Also I have not tested it properly so if you wish to accept it then please do testing.
var oldObj = _objectiveDetailService.GetObjectiveDetails(id);
var newObj = objective.ObjectiveDetails.ToList();
var upd = newObj
.Where(wb => oldObj
.Any(db => (db.ObjectiveDetailId == wb.ObjectiveDetailId) &&
(db.Number != wb.Number || !db.Text.Equals(wb.Text))))
.ToList();
newObj.ForEach(wb =>
{
var comOld = oldObj.Where(db => wb.ObjectiveDetailId == db.ObjectiveDetailId &&
db.Number == wb.Number && db.Text.Equals(wb.Text)).FirstOrDefault();
if (comOld != null && wb.SubTopics.Any(wb2 => comOld.SubTopics.Where(oldST => wb2.SubTopicId == oldST.SubTopicId).Any(a => !a.Name.Equals(wb2.Name))))
{
upd.Add(wb);
}
});
You can write similar code to add and delete as well.
Hope this helps.
IList<ObjectiveDetail> upd = newObj
.Where(wb => oldObj
.Any(db => (db.ObjectiveDetailId == wb.ObjectiveDetailId) &&
(db.Number != wb.Number || !db.Text.Equals(wb.Text)))
||!oldObj.Any(o=>o.DetailId == wb.DetailId) //check if it's there or a new one
//check count
|| ((wb.SubTopics.Count!= oldObj.FirstOrDefault(o=>o.DetailId == wb.DetailId).SubTopics.Count
|| //check Ids match, or you can add more properties with OR
wb.SubTopics.Any(wbs=>oldObj.FirstOrDefault(o=>o.DetailId == wb.DetailId)
.SubTopics.Any(obs=>obs.SubTopicId !=wbs.SubTopicId))))
).ToList();
Have a look at below code. I created this function to compare two object then returns matched properties fields as an object.It may help full to you.
/// <summary>
/// Compare two objects, returns destination object with matched properties, values. simply Reflection to automatically copy and compare properties of two object
/// </summary>
/// <param name="source"></param>
/// <param name="destination"></param>
/// <returns>destination</returns>
public static object CompareNameAndSync(object source, object destination)
{
Type stype = source.GetType();
Type dtype = destination.GetType();
PropertyInfo[] spinfo = stype.GetProperties();
PropertyInfo[] dpinfo = dtype.GetProperties();
foreach (PropertyInfo des in dpinfo)
{
foreach (PropertyInfo sou in spinfo)
{
if (des.Name == sou.Name)
{
des.SetValue(destination, sou.GetValue(source));
}
}
}
return destination;
}

Get dictionary key object properties

I am trying to retrieve a dictionary's key property, as the key is a class. How do you do it? Here is the class that I use:
public class Item
{
public int Sku { get; set; }
public string Name { get; set; }
public Item()
{
}
}
I am trying to retrieve a property of it for example Name:
Dictionary<Item,double> myDictionary = new Dictionary<Item,double>();
Item item = new Item { Sku = 123, Name = "myItem" };
myDictionary.Add(item,10.5);
So now for example how from this dictionary I would retrieve the item's Name or Sku, or any other property if it would have them?
First, you have to override GetHashCode and Equals if you want to use your class as key of a Dictionary, otherwise you're comparing references.
Here's an example where Equals checks if two items have the same Name.
public class Item
{
public override int GetHashCode()
{
return Name == null ? 0 : Name.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj == null) return false;
if(object.ReferenceEquals(this, obj)) return true;
Item i2 = obj as Item;
if(i2 == null) return false;
return StringComparer.CurrentCulture.Equals(Name, i2.Name);
}
// rest of class ...
}
But the question is not clear. You use a dictionary to lookup elements by the key. So you want to find the value by providing the key. That means you have already a key which makes your question pointless.
However, you can loop a dictionary even if it's not made for this:
foreach(var kv in mydictronary)
{
Item i = kv.Key;
// now you have all properties of it
}
To retrieve your item, you need to use the same item (the same reference). You can do it in such way:
var myDouble = myDictonary[item];
When you use object as a key in a directory, its hash code is use to add/retrieve item from it - you can read more here
If you want use a string to retrieve items, then you should use strings as a key in you dictionary:
Dictonary<string,double> mydictronary = new Dictonary<string,double>();
you can iterate of the dictionary like this:
foreach(var keyValuePair in myDictionary)
{
kvp.Key.
}
then youll get all of the properties
You can use linq:
var item = myDictionary.Where(x => x.Key.Name == "myItem");
var item = myDictionary.Where(x => x.Key.Sku == 123);
You have three options.
You can use the same instance of the class to index, as in var x = myDictionary[item].
You can implementa customer comparer (something that implements IEqualityComparer<Item>), and pass that in to the constructor of your dictionary. For details see MSDN.
You can implement IEquatable<Item> on your Item class. For details see IEquatable on MSDN.
You can access keys from the Dictionary<TKey, TValue>.Keys property.
From MSDN
// To get the keys alone, use the Keys property.
Dictionary<string, string>.KeyCollection keyColl = openWith.Keys;
// The elements of the KeyCollection are strongly typed
// with the type that was specified for dictionary keys.
Console.WriteLine();
foreach( string s in keyColl )
{
Console.WriteLine("Key = {0}", s);
}

Insert an object in the list in C#

I have a list of class objects UserData. I get an object from this list through where method
UserData.Where(s => s.ID == IDKey).ToList(); //ID is unique
I would like to make some changes in the object and insert at the same location in the list. However, I donot have the index of this object.
Any idea how to do it ?
Thanks
You can get the index using the method
UserData.FindIndex(s => s.ID == IDKey)
It will return an int.
When your getting the item from a LIST its an reference type, if your updating anything to it then it will automatically change the values in LIST. Please check your self after updating...........
Item whichever your getting from
UserData.Where(s => s.ID == IDKey).ToList();
is an reference type.
As long as UserData is reference type, the list only holds references to instances of that object. So you can change its properties without the need of remove/insert (and obviously do not need index of that object).
I also suggest you want to use Single method (instead of ToList()) as long as the id is unique.
Example
public void ChangeUserName(List<UserData> users, int userId, string newName)
{
var user = users.Single(x=> x.UserId == userId);
user.Name = newName; // here you are changing the Name value of UserData objects, which is still part of the list
}
just fetch the object using SingleOrDefault and make related changes; you do not need to add it to the list again; you are simply changing the same instance which is an element of the list.
var temp = UserData.SingleOrDefault(s => s.ID == IDKey);
// apply changes
temp.X = someValue;
If I'm misunderstanding you then please correct me, but I think you're saying that you essentially want to iterate through the elements of a list, and if it matches a condition then you want to alter it in some way and add it to another list.
If that's the case, then please see the code below to see how to write an anonymous method using the Where clause. The Where clause just wants an anonymous function or delegate which matches the following:
parameters: ElementType element, int index -- return: bool result
which allows it to either select or ignore the element based upon the boolean return. This allows us to submit a simple boolean expression, or a more complex function which has additional steps, as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace StackOverflow
{
class Program
{
static void Main(string[] args)
{
int IDKey = 1;
List<SomeClass> UserData = new List<SomeClass>()
{
new SomeClass(),
new SomeClass(1),
new SomeClass(2)
};
//This operation actually works by evaluating the condition provided and adding the
//object s if the bool returned is true, but we can do other things too
UserData.Where(s => s.ID == IDKey).ToList();
//We can actually write an entire method inside the Where clause, like so:
List<SomeClass> filteredList = UserData.Where((s) => //Create a parameter for the func<SomeClass,bool> by using (varName)
{
bool theBooleanThatActuallyGetsReturnedInTheAboveVersion =
(s.ID == IDKey);
if (theBooleanThatActuallyGetsReturnedInTheAboveVersion) s.name = "Changed";
return theBooleanThatActuallyGetsReturnedInTheAboveVersion;
}
).ToList();
foreach (SomeClass item in filteredList)
{
Console.WriteLine(item.name);
}
}
}
class SomeClass
{
public int ID { get; set; }
public string name { get; set; }
public SomeClass(int id = 0, string name = "defaultName")
{
this.ID = id;
this.name = name;
}
}
}

Categories