This question already has answers here:
Update all objects in a collection using LINQ
(18 answers)
Closed 7 years ago.
I am trying to add a SELECT ALL functionality to my grid with LINQ, but I get a compilation error.
List<Person_> PeopleUpdated = People.ToList().ForEach(a => a.SELECTED = true).ToList();
It says
Cannot implicitly convert type 'void' to
'System.Collections.Generic.List <
LogoSapHrIntegration.frmXmlUpload.Person_>'
what am I doing wrong?
The List<T>.ForEach has no return value (ie void), so you can't run ToList() against that. (see MSDN)
ForEach a specific action for each item in the list (just like doing a real for loop).
In your case a simple for loop to select all is most efficient.
foreach (var person in People)
person.Selected = true
List<T>.ForEach returns void (in your case, it changes your collection in place). ForEach takes an Action<T> and executes that on each item of your list.
See List(T).ForEach on MSDN
The ForEeach method (which is not LINQ) runs an action on each item in the list, it's not used to filter out items from a list so it doesn't return a result.
Just run the method on each item; there is no result to assign:
People.ToList().ForEach(a => a.SELECTED = true);
If you wanted a new list of items where the property was changed, you would need to clone the items to make them separate from the originals:
List<Person_> PeopleUpdated = People.ToList().Select(a => {
Person_ b = a.Clone();
b.SELECTED = true;
return b;
}).ToList();
(If the class doesn't support cloning, you would need to implement the Clone method (and preferably the IClonable interface).)
First of all, you can use a normal foreach loop:
foreach (var person in people)
{
person.Selected = true;
}
Which is the simplest and cleanest.
If you really want to jump to hoops and use LINQ, you can use ConvertAll:
var list = new List<Person> { new Person(), new Person() };
var convertedPeople = list.ConvertAll(person =>
{
person.Selected = true;
return person;
});
Related
This question already has answers here:
Item from IEnumerable changed inside foreach, but change not saved to collection
(1 answer)
C# failing to set property inside IEnumerable
(5 answers)
Closed 3 years ago.
I have this code:
class Foo
{
public string A { get; set; }
}
class Program
{
static void Main(string[] args)
{
var strings = new List<string> { "foo", "foo" };
var list = strings.Select(x => new Foo { A = x });
foreach (var item in list)
{
item.A = "bar";
}
foreach (var item in list)
{
Console.WriteLine(item.A);
}
}
}
Which prints:
foo
foo
What exactly happens when you set item.A = "bar" ?
After the first foreach loop finishes, does the list var really contain the same two Foo objects with "bar" as the new string?
If so, how could you access these new values?
I understand that when the 2nd foreach loop runs, it is enumerating the collection of strings which is why you get two print outs of "foo", but I'm just confused as to what happens when item.A = "bar" is run, and if you are never able to access that new value, why does the compiler allow you to modify it?
What's happening here is that you are creating an enumerable list which you are enumerating multiple times.
Each time you enumerate list, the enumeration processes the elements of the strings list calling new Foo { A = x } for each element to create the elements of the resulting sequence.
That means the the Foo objects created by the first foreach enumeration are NOT the same as the ones created by the second foreach enumeration. New ones are created for each enumeration.
This is the reason that Resharper warns about "possible multiple enumeration".
To avoid this, you would use var list = strings.Select(x => new Foo { A = x }).ToList(); to enumerate the sequence just once and store the results in an actual List<T>.
The problem is that you haven't called ToList method to materialize your LINQ query. When you call ToList as below:
var list = strings.Select(x => new Foo { A = x })
.ToList();
an in-memory collection of Foo objects would be created, whose property value A would have the value x. Essentially two new objects of type Foo would be created with the value of A to be "foo". Then you can loop through this list and modify the property value.
Please look at this fiddle
You are right that if will not going to be chnaged, then why compiler allow. but if you want to print without updating actual item in this scenario above code will helpful.
One thing you should know that, you can not modified the item of IEnumerable object.
you have to use List();
var strings = new List<string> { "foo", "foo" };
var list = strings.Select(x => new Foo { A = x }).ToList();
foreach (var item in list)
{
item.A = "bar";
}
foreach (var item in list)
{
Console.WriteLine(item.A);
}
I want to convert from List<IEnumerable<object>> to List<object> in C#
currently I am achieving this by looping 2 times like below.
// distributerFreezerList is List<IEnumerable<FreezerTagViewModel>>
List<FreezerTagViewModel> taglist = new List<FreezerTagViewModel>();
foreach (var one in distributerFreezerList)
{
foreach (var two in one)
{
FreezerTagViewModel tag = new FreezerTagViewModel();
tag = two;
}
}
Is there any easy way?
You could use the SelectMany in Linq for this. It flattens the nested list.
distributerFreezerList.SelectMany(item => item).ToList()
The SelectMany returns a IEnumerable<object>, so added a ToList to make it a list.
This question already has answers here:
Flatten List in LINQ
(5 answers)
Closed 6 years ago.
I'm trying to perform an run an extension method on every item within a List<> that is inside another List<> to return collection of a given type (returned by the extension method).
I initially tried (and failed) to do this using linq, but I have the following:
var dataset = GetReportDataset(org);
var reportData = new List<InterventionAndNeetRiskReportLineModel>();
foreach (var record in dataset)
{
foreach (var inter in record.InterventionHistory)
{
reportData.Add(inter.ToInterventionAndNeetRiskReportLineModel());
}
}
return _reportWriter.ReportCsvStream(reportData);
So my question is, how can I project the result of my extension method for each item in the child collection using linq?
UPDATE ToInterventionAndNeetRiskReportLineModel() extension method
public static InterventionAndNeetRiskReportLineModel ToInterventionAndNeetRiskReportLineModel(this InterventionHistory intervention)
{
return new InterventionAndNeetRiskReportLineModel()
{
Beneficiary = intervention.Person.Beneficiary,
CourseTitle = intervention.CourseTitle,
CaseNotes = intervention.CaseNotes,
EndDate = intervention.EndDate?.ToString(),
StartDate = intervention.StartDate.ToString(),
ParticipantId = intervention.Person.ParticipantId,
FirstEit = intervention.Person.EitScores.GetFirstEitReading().ToString(),
LastEit = intervention.Person.EitScores.GetLastEitReading().ToString(),
FirstLpt = intervention.Person.LptScores.GetFirstLptReading().ToString(),
LastLpt = intervention.Person.LptScores.GetLastLptReading().ToString(),
Gender = intervention.Person.Equalitites.Gender,
HoursAttended = intervention.NoOfHours.ToString(),
LanguageOfDelivery = intervention.DeliveryLanguage,
Providername = intervention.ProviderName,
QanCode = intervention.QanCode,
SchoolCollegeName = intervention.ProviderName
};
}
I'm not completely sure which part of the question code you want to separate into an extension method. Also, don't be to focused on the extension method part, its nothing different from other functions, as far as the writing is concerned.
You can use SelectMany in order to get a flat list of InterventionHistory objects and Select in order to convert to InterventionAndNeetRiskReportLineModel and ToList for the final result as list instead of IEnumerable<T> if you really need that.
var reportData = GetReportDataset(org)
.SelectMany(r => r.InterventionHistory)
.Select(i => i.ToInterventionAndNeetRiskReportLineModel())
.ToList();
So, maybe you want an extension method like
public static IEnumerable<InterventionAndNeetRiskReportLineModel> ToInterventionRiskReports(this IEnumerable<ReportDataset> _self)
return _self
.SelectMany(r => r.InterventionHistory)
.Select(i => i.ToInterventionAndNeetRiskReportLineModel());
}
And use it as
var reportData = GetReportDataset(org).ToInterventionRiskReports().ToList();
... as I said, its not completely clear, which part you want to refactor into an extension method.
This is a long shot, I know...
Let's say I have a collection
List<MyClass> objects;
and I want to run the same method on every object in the collection, with or without a return value. Before Linq I would have said:
List<ReturnType> results = new List<ReturnType>();
List<int> FormulaResults = new List<int>();
foreach (MyClass obj in objects) {
results.Add(obj.MyMethod());
FormulaResults.Add(ApplyFormula(obj));
}
I would love to be able to do something like this:
List<ReturnType> results = new List<ReturnType>();
results.AddRange(objects.Execute(obj => obj.MyMethod()));
// obviously .Execute() above is fictitious
List<int> FormulaResults = new List<int>();
FormulaResults.AddRange(objects.Execute(obj => ApplyFormula(obj)));
I haven't found anything that will do this. Is there such a thing?
If there's nothing generic like I've posited above, at least maybe there's a way of doing it for the purposes I'm working on now: I have a collection of one object that has a wrapper class:
class WrapperClass {
private WrappedClass wrapped;
public WrapperClass(WrappedClass wc) {
this.wrapped = wc;
}
}
My code has a collection List<WrappedClass> objects and I want to convert that to a List<WrapperClass>. Is there some clever Linq way of doing this, without doing the tedious
List<WrapperClass> result = new List<WrapperClass>();
foreach (WrappedClass obj in objects)
results.Add(new WrapperClass(obj));
Thanks...
Would:
results.AddRange(objects.Select(obj => ApplyFormula(obj)));
do?
or (simpler)
var results = objects.Select(obj => ApplyFormula(obj)).ToList();
I think that the Select() extension method can do what you're looking for:
objects.Select( obj => obj.MyMethod() ).ToList(); // produces List<Result>
objects.Select( obj => ApplyFormula(obj) ).ToList(); // produces List<int>
Same thing for the last case:
objects.Select( obj => new WrapperClass( obj ) ).ToList();
If you have a void method which you want to call, here's a trick you can use with IEnumerable, which doesn't have a ForEach() extension, to create a similar behavior without a lot of effort.
objects.Select( obj => { obj.SomeVoidMethod(); false; } ).Count();
The Select() will produce a sequence of [false] values after invoking SomeVoidMethod() on each [obj] in the objects sequence. Since Select() uses deferred execution, we call the Count() extension to force each element in the sequence to be evaluated. It works quite well when you want something like a ForEach() behavior.
If the method MyMethod that you want to apply returns an object of type T then you can obtain an IEnumerable<T> of the result of the method via:
var results = objects.Select(o => o.MyMethod());
If the method MyMethod that you want to apply has return type void then you can apply the method via:
objects.ForEach(o => o.MyMethod());
This assumes that objects is of generic type List<>. If all you have is an IEnumerable<> then you can roll your own ForEach extension method or apply objects.ToList() first and use the above syntax .
The C# compiler maps a LINQ select onto the .Select extension method, defined over IEnumerable (or IQueryable which we'll ignore here). Actually, that .Select method is exactly the kind of projection function that you're after.
LBushkin is correct, but you can actually use LINQ syntax as well...
var query = from o in objects
select o.MyMethod();
You can also run a custom method using the marvelous Jon Skeet's morelinq library
For example if you had a text property on your MyClass that you needed to change in runtime using a method on the same class:
objects = objects.Pipe<MyClass>(class => class.Text = class.UpdateText()).ToList();
This method will now be implemented on every object in your list. I love morelinq!
http://www.hookedonlinq.com/UpdateOperator.ashx has an extended Update method you can use. Or you can use a select statement as posted by others.
I want to union, merge in a List that contains both references, so this is my code, how can I define a list ready for this porpouses?
if (e.CommandName == "AddtoSelected")
{
List<DetalleCita> lstAux = new List<DetalleCita>();
foreach (GridViewRow row in this.dgvEstudios.Rows)
{
var GridData = GetValues(row);
var GridData2 = GetValues(row);
IList AftList2 = GridData2.Values.Where(r => r != null).ToList();
AftList2.Cast<DetalleCita>();
chkEstudio = dgvEstudios.Rows[index].FindControl("ChkAsignar") as CheckBox;
if (chkEstudio.Checked)
{
IList AftList = GridData.Values.Where(r => r != null).ToList();
lstAux.Add(
new DetalleCita
{
codigoclase = Convert.ToInt32(AftList[0]),
nombreestudio = AftList[1].ToString(),
precioestudio = Convert.ToDouble(AftList[2]),
horacita = dt,
codigoestudio = AftList[4].ToString()
});
}
index++;
//this line to merge
lstAux.ToList().AddRange(AftList2);
}
dgvEstudios.DataSource = lstAux;
dgvEstudios.DataBind();
}
this is inside a rowcommand event.
If you want to add all entries from AftList2 to lstAux you should define AftList2 as IEnumerable<> with elements of type DetalleCita (being IEnumerable<DetalleCita> is enough to be used as parameter of AddRange() on List<DetalleCita>). For example like this:
var AftList2 = GridData2.Values.Where(r => r != null).Cast<DetalleCita>();
And then you can add all its elements to lstAux:
lstAux.AddRange(AftList2);
Clarification:
I think you are misunderstanding what extension method ToList() does. It creates new list from IEnumerable<T> and its result is not connected with original IEnumerable<T> that it is applied to.
That is why you are just do nothing useful trying to do list.ToList().AddRange(...) - you are copying list to (another newly created by ToList()) list, update it and then basically throwing away it (because you are not even doing something like list2 = var1.ToList(), original var1 stays unchanged after that!!! you most likely want to save result of ToList() if you are calling it).
Also you don't usually need to convert one list to another list, ToList() is useful when you need list (List<T>) but have IEnumerable<T> (that is not indexable and you may need fast access by index, or lazy evaluates but you need all results calculated at this time -- both situations may arise while trying to use result of LINQ to objects query for example: IEnumerable<int> ints = from i in anotherInts where i > 20 select i; -- even if anotherInts was List<int> result of query ints cannot be cast to List<int> because it is not list but implementation of IEnumerable<int>. In this case you could use ToList() to get list anyway: List<int> ints = (from i in anotherInts where i > 20 select i).ToList();).
UPDATE:
If you really mean union semantics (e.g. for { 1, 2 } and { 1, 3 } union would be something like { 1, 2, 3 }, with no duplication of equal elements from two collections) consider switching to HashSet<T> (it most likely available in your situation 'cause you are using C# 3.0 and I suppose yoou have recent .NET framework) or use Union() extension method instead of AddRange (I don't think this is better than first solution and be careful because it works more like ToList() -- a.Union(b) return new collection and does NOT updates either a or b).