I have this code to modify the categorie list foreach opened Form
var lst = Application.OpenForms.OfType<FrmProduit>();
foreach (var item in lst)
{
item.getCategorie(Categories.getLastCategorieId());
}
Well, the first loop is ok, but then second loop I have the InvalidOperationExcetion
Any help please
Try using the List<T> ForEach method as follows:
Application.OpenForms.OfType<FrmProduit>()
.ToList()
.ForEach(i => i.getCategorie(Categories.getLastCategorieId()));
This will not throw the error - but if the 'getCategorie' method has a return value, you might want to do something with it. If that's the case, you need:
Application.OpenForms.OfType<FrmProduit>()
.ToList()
.ForEach(i =>
{
var retVal = i.getCategorie(Categories.getLastCategorieId());
// do something with retVal here...
});
Related
I would like to request you to help me with this problem. I have an Observable Collection that stores favourites and I load items to another Observable Collection, so, what I want is for the new items which have unique IDs to be checked against Favourites Observable Collection in an efficient way as I feel what I am doing is not good enough.
What I am currently doing is as follows:
foreach (var item in AllItems)
{
if (Watchlist.Fav.Count != 0)
{
if (Watchlist.Fav.Any(s => s.Id == item.Id)))
{
Watchlist.Fav.Remove(Watchlist.Fav.SingleOrDefault(i => i.Id == item.Id));
Watchlist.Fav.Add(item);
item.IsFavorite = true;
ItmesCollection.Add(item);
}
}
}
Could someone please help me make this better?
Cheers guys!
Since OP is asking a better syntax of current working code. Here is a try:
foreach (var item in AllItems)
{
// no need check Watchlist.Fav.Count, because .Any duplicates
// store matchingFav in variable so no need query twice
var matchingFav = Watchlist.Fav.SingleOrDefault(s => s.Id == item.Id)));
if (matchingFav != null)
{
matchingFav.IsFavorite = true;
// where is ItemsCollection from? background not clear, so no change
ItemsCollection.Add(item);
}
}
If the last statement is not relavant, syntax can be even shorter:
var ids = new HashSet<int>(AllItems.Select(x => x.Id));
foreach (var matchingFav in Watchlist.Fav
.Where(x => ids.Contains(x.Id)))
{
matchingFav.IsFavorite = true;
}
I am trying to convert this to a linq statement with method syntax. I am not sure how to do it when teh foreach loop has an if statement. In the code below, MyMethodToConvert replaces the string "Tomorrow" to DateTime.Now
foreach (var data in MyCollection)
{
if (data.DeliveryDate.Equals("Tomorrow"))
{
data.DeliveryDate = MyMethodToConvert(DeliveryDate);
}
}
I tried this, t didn't work
MyCollection = MyCollection.Select(a =>
{
a.DeliveryDate.Equals("Tomorrow")
? MyMethodToConvert(DeliveryDate)
: a.DeliveryDate)
;
return a;
}).ToList();
But it didn't work.
Go only this far:
foreach (var data in MyCollection.Where(x => x.DeliveryDate.Equals("Tomorrow")))
{
data.DeliveryDate = MyMethodToConvert(DeliveryDate);
}
If the compile-time type of x.DeliveryDate is string, prefer:
foreach (var data in MyCollection.Where(x => x.DeliveryDate == "Tomorrow"))
{
data.DeliveryDate = MyMethodToConvert(DeliveryDate);
}
You could use this:
MyCollection = MyCollection.Select(data =>
{
if (data.DeliveryDate.Equals("Tomorrow"))
data.DeliveryDate = MyMethodToConvert(DeliveryDate);
return data;
}).ToList();
Or, if you don't want any Semicolons in your code (I'll assume that you have a class named Delivery with a constructor just for the DeliveryDate):
MyCollection = MyCollection.Select(data => data.DeliveryDate.Equals("Tomorrow")
? new Delivery(MyMethodToConvert(DeliveryDate))
: data).ToList();
However, I wouldn't suggest to use Linq in here. The only little bit useful use of Linq would be what Jeppe Stig Nielsen suggested.
How about this:
MyCollection.Where(d => d.DeliveryDate.Equals("Tomorrow"))
.ToList()
.ForEach(d => d.DeliveryDate = MyMethodToConvert(DeliveryDate));
I'm a beginner with LINQ.
How can I convert this to a LINQ statement?
List<Foo> myList = new List<Foo>();
myList.AddRange(// here I add my items);
foreach (Foo x in myList)
{
if (x.IsRequired() == false) throw new Exception();
}
to a LINQ statement? Like:
myList.ForEach(x => //something here);
I tried the following but that didn't work for me.
myList.ForEach(x => if (x.IsRequired() == false) throw new Exception());
I'd say
if (MyList.Any(x => x.IsRequired() == false))
{
throw new Exception();
}
IsRequired() It's a method that returns a Boolean
so you can also shorten
if (MyList.Any(x => !x.IsRequired()))
{
throw new Exception();
}
The answer that fubo gave is good if you just want to see if any of the elements in your list is not required. If you want to get the actual element(s), you can do it like this:
First Element
Foo notRequired = MyList.FirstOrDefault(x => !x.IsRequired());
if ( notRequired != null)
{
// Do something with `notRequired`
}
All Elements
IEnumerable<Foo> notRequired = MyList.Where(x => !x.IsRequired());
if (notRequired.Count() > 0)
{
foreach (var v in notRequired)
{
// Do something with `v`
}
}
After reading your comments and the additional information :
The problem is that I want to find all Foo elements in myList which are not required. It's seems not possible with the Any method, it will fail on the first one.
Assuming Foo has some information that you would like to pass to your exception like a string Information you could get all of them assign them to a new list and check then for Any(). and do all that in the If-Clause:
List<Foo> temp = new List<Foo>();
if ((temp = MyList.Where(x=>!x.IsRequired()).ToList()).Any())
{
// now pass the information of them all into the exception
throw new Exception(String.Join("\t", temp.Select(y=>y.Information)));
}
Officially ForEach is not a LINQ statement. It usually only works for Lists.
From your code I assume that you want to throw an exception if any of the Foo objects in MyList has a false IsRequiredvalue.
You statement would be:
if (MyList.Any(foo => !foo.IsRequired))
throw new Exception();
In words: if any of the foo elements in MyList has a false IsRequired value, throw a new Exception
The nice thing from using Any instead of first creating a list before checking, is that if you have an IEnumerable, and one of the first elements in the list would throw an exception, the rest of your list would not have been created in vain. See StackOverflow: What are the benefits of deferred execution?
Later you wrote:
The problem is that I want to find all Foo elements in myList which
are not required. It's seems not possible with the Any method, it will
fail on the first one.
If you want to find all Foo elements in the list that are not required, you still can use Linq, using Enumerable.Where:
var notRequiredFoos = myList
.Where(elementInList => !elementInList.IsRequired);
usage:
foreach (var notRequiredFoo in notRequiredFoos)
{
Console.WriteLine($"Foo element {notRequiredFoo.ToString} is not required");
}
Or if you want to throw an exception as soon as you found one, Linq will still help you: Enumerable.FirstOrDefault
var notRequiredFoo= myList
.Where(elementInList => !elementInList.IsRequired);
.FirstOrDefault();
if (notRequiredFoo != null)
{ // we found a Foo that is not required
throw new MyException(notRequiredFoo);
}
// else: all Foos are required
Again, you still don't have to check all elements in the list, it will stop as soon as one is found.
I have applied IGrouping<> over a list - here's what it looks like:
IEnumerable<IGrouping<TierRequest,PingtreeNode>> Tiers
{
get { return ActiveNodes.GroupBy(x => new TierRequest(x.TierID, x.TierTimeout, x.TierMaxRequests)); }
}
Later in my code I iterate over Tiers. Its simple to get the key data using the Key element, but how do I get the IEnumerable<PingtreeNode> that forms the value part?
Thanks in advance
Tiers.Select(group => group.Select(element => ...));
in foreach you can get values like this
foreach(var group in tiers)
{
TierRequest key = group.Key;
PingtreeNode[] values = group.ToArray();
}
The group itself implements IEnumerable<T> and can be iterated over, or used with linq methods.
var firstGroup = Tiers.First();
foreach(var item in firstGroup)
{
item.DoSomething();
}
// or using linq:
firstGroup.Select(item => item.ToString());
// or if you want to iterate over all items at once (kind of unwinds
// the grouping):
var itemNames = Tiers.SelectMany(g => g.ToString()).ToList();
Friends,
I know how to deploy and retrieve a single element in LINQ, but how can I do to change all the properties in a list. In the line below, I can only modify a record, I would modify several.
_ListaAcaoMenuInfo.Where(p => p.Id_acao == id).FirstOrDefault().Id_menu = 0;
Thanks
Use the ForEach function of a List...
_ListaAcaoMenuInfo.Where(p => p.Id_acao == id).ToList().ForEach(item=>item.Id_menu=0);
You wouldn't want to. LINQ is not to be used for side effects. There's a foreach loop for that.
foreach (var x in collection.where(x => x.Foo = "Blah"))
x.Foo = "Bar";
Use foreach:
var l = _ListaAcaoMenuInfo.Where(p => p.Id_acao == id).ToList();
foreach (Thing i in l)
{
i.Id_menu = 0;
//now use your Context object to save back to the database
}