How to change values while looping through an IEnumerable - c#

I keep getting stuck on this issue and have done a lot of searching/reading to try to understand the problem, but I just don't get it. Am wondering if someone can provide me with an example of how to update object values while looping an IEnumerable<>.
Example:
public class MyClass
{
private IEnumerable<MyData> _MyData = null;
public MyClass() {}
public MyClass(string parm1, int parm2) { Load(parm1, parm2); }
public IEnumerable<MyData> Load(string parm1, int parm2)
{
_MyData = _dbContext.MyData.Where(m => m.Parm1 == parm1 && m.Parm2 == parm2);
foreach(MyData mydata in _MyData)
{
if(mydata.Parm2 == 1)
{
mydata.Parm1 = "Some value";
}
}
return _MyData;
}
}
The above code doesn't work as any changes made to mydata.Parm1 within the loop are not retained. I read an SO article that suggested to make changes like this:
for (int i = 0; i < _MyData.Count(); i++)
{
_MyData.Skip(i).FirstOrDefault().Parm1 = "Some Value";
}
This works, but it's really ugly and hard for me to believe there isn't a cleaner way. For a single change it might be acceptable, but I have several changes that need to be made. So I've attempted this:
for (int i = 0; i < _MyData.Count(); i++)
{
MyData md = _MyData.ElementAt(i);
md.Parm1 = "Some Value";
}
But I don't understand how to put the modified md back into _MyData to save changes.
I think the main reason I'm going through all of these hoops is that I don't understand how to make changes to the elements and have them retained. Any changes I make seem to revert back to their original values unless I go through these hoops. Maybe someone can point out where I'm going wrong. I would like to use this class like this:
IEnumerable<MyData> MyDataResult = new MyClass("Parm1", 4);
Using the above line of code, I can trace through the Load() function and see that the desired changes are being made, but once finished MyDataResult contains the original values instead of those I saw being changed.
It is more then obvious that my code is wrong, but I hope I've been clear enough to illustrate what I'm wanting to do and where I'm having difficulty.

Try this -
_MyData = _dbContext.MyData.Where(m => m.Parm1 == parm1 && m.Parm2 == parm2).ToList();
To be clear, essentially what you have in your current code is a query, which you are enumerating in your Load method, trying to update some of its properties, but then in the end, you end up returning the query, and not the updated values in the query.
The caller of Load method, will end up running the query a second time, only to see direct values from the database.
Adding .ToList to the end of the query in Load method, materializes the query, and then you are doing rest of the operations in memory.
EDIT:
Just in case, if there would be performance concern over the large amount of data this query may return, then you could also consider this alternate approach -
public IEnumerable<MyData> Load(string parm1, int parm2)
{
_MyData = _dbContext.MyData.Where(m => m.Parm1 == parm1 && m.Parm2 == parm2);
foreach(MyData mydata in _MyData)
{
if(mydata.Parm2 == 1)
{
mydata.Parm1 = "Some value";
}
yield return myData;
}
}
This would keep the query lazy, and still return the modified values, as caller of Load iterates over the IEnumerable<MyData> returned by Load.

Not sure why you are returning a value which never gets used. You just need to set _MyData in your Load method as it is a class level variable.
Change Load to not return a value and ToList() your query on the db context and then set your _MyData to your concrete list object in Load.
Something like this will work - I've simplified your example slightly but same principals:
public class MyClass
{
public IEnumerable<string> _MyData = null;
public IEnumerable<string> _dbContext = new List<string> {"a", "b", "aa", "bb"};
public MyClass(){}
public MyClass(string parm1, int parm2){Load(parm1, parm2);}
public void Load(string parm1, int parm2)
{
var somedata = _dbContext.Where(m => m.Length == 2).ToList();
var myData = somedata.Select(s => s == parm1 ? "something else" : s).ToList();
_MyData = myData;
}
}
Use can use
var a = new MyClass("aa",1)._MyData;
and "aa" will get replaced with "something else" and be returned to "a".
You can't use a class like this:
IEnumerable<MyData> MyDataResult = new MyClass("Parm1", 4);
If you ask for an MyClass you'll get a MyClass not an IEnumerable.
If your call to dbContext is to an underlying data source you may be better off not doing that in the class constructor and always call Load explicitly following class construction. You then have options to avoid thread blocking on a potentially long running I/O operation.

Related

How to convert float to system.Collection.generic.IEnumerable

How to convert float to system.Collection.generic.IEnumerable
The actual problem occurs when I try to iterate through the returned IEnumerable.
Code
private ObservableRangeCollection<ReviewInfo> _rating = new ObservableRangeCollection<ReviewInfo>();
public ObservableRangeCollection<ReviewInfo> Review
{
get { return _rating; }
set { _rating = value; OnPropertyChanged("AvRating"); }
}
public async Task GetReview()
{
var ber_id= berProfile.Id;
ResponseInfo<ReviewInfo> res = await nsManager.Instance.GetReview(ber_id);
Device.BeginInvokeOnMainThread(async () => {
IsBusy = false;
if (res.IsError == true)
{
await _page.Alert(res.Message);
}
else
{
if (res.Data != null && res.Data.Count > 0)
{
var temp = res.Data.Average(x => x.Rating);
Review.AddRange(temp);
}
}
});
}
Review is a collection of GogroomCustomer.Models.ReviewInfo, so you should create ReviewInfo object from temp by constructor or set via Property (ex: reviewInfo), then use Add or AddRange method:
Review.Add(reviewInfo);
or
Review.AddRange(new ReviewInfo[] { reviewInfo });
Your question is quite unclear as you didn´t provide what a ReviewInfo is. However your error is quite clear: you´re trying to add a float to a list of ReviewInfo. Of course this won´t work.
From your code I suppose this class has at least a Rating-property or field. Assuming you have a list of those ReviewInfo-instances you probably want to retrieve that object whose Rating-property is the average of all the elements within your list.
If this is the case your solution is simply this:
var temp = res.Data.Average(x => x.Rating);
Review.Add(res.Data.First(x.Rating == tmp));
However as Average returns a double it is fairly possible that there´s no element with exactly this rating in your list, so it´s better to apply some tolerance. However this goes too far on guessing what you actually want.

Unit Testing: Can't figure this out?

I'm doing a unit test in my design class, and the shell of the project was given to us. There is only one method in the unit test where I have to add code. I can't change anything else in the code.
I have tried everything I could think of using what C++ knowledge I have and tried Googling different ways to solve this problem. Every result that came up was either too complex because I don't have a background with C#, or the information for what I was looking for was not given.
Here is the original code:
class Course
{
public Course(string id, string title, int creditHours, string description, string prerequisiteCourse)
{
this.CourseID = id;
this.CourseTitle = title;
this.CreditHours = creditHours;
this.Description = description;
this.PrerequisiteCourse = prerequisiteCourse;
}
public string CourseID;
public string CourseTitle;
public int CreditHours;
public string Description;
public string PrerequisiteCourse;
}
class CourseListTest
{
public static void Main(string[] args)
{
GetCourseByCourseIDTestWhenCourseExists();
GetCourseByCourseIDTestWhenCourseDoesNotExist();
}
public static void GetCourseByCourseIDTestWhenCourseExists()
{
CourseList myCourseList = new CourseList();
Course myCourse = myCourseList.GetCourseByCourseID("CIS 400");
if (myCourse.CourseID != "CIS 400")
System.Console.WriteLine("ERROR - GetCourseByCourseIDTestWhenCourseExists(): Returned CourseID Not equal (CIS 400)");
}
public static void GetCourseByCourseIDTestWhenCourseDoesNotExist()
{
CourseList myCourseList = new CourseList();
Course myCourse = myCourseList.GetCourseByCourseID("CIS 101");
if (myCourse != null)
System.Console.WriteLine("ERROR - GetCourseByCourseIDTestWhenCourseDoesNotExist(): should have returned null");
}
}
Here is were the problem lies in the next class. We are to enter code into the GetCourseByCourseID method which is where I get stuck.
class CourseList
{
public Course[] CourseArray =
{
new Course ("CIS 400", "OO Analysis & Design", 4, "Important class", "CIS 110") ,
new Course ("CIS 150A" , "VB.NET Programming", 4, "Good Introduction to programming", "CIS 100") ,
new Course ("CIS 150B", "C# Programming with labs", 4, "Follow-up to CIS 100", "CIS 100")
};
public Course GetCourseByCourseID(string id)
{
}
}
Since "CIS 101" is not a course in the CourseList we have to return null. The whole point of the exercise is to get the console to display nothing. That means the code is working properly.
I don't want the answer. I was just wanted an example of how to get this to work. Being that the code was already given to us.
i'll keep this close to c++ syntax.
there are many other ways but...
public Course GetCourseByCourseID(string id)
{
for(int x = 0; x < CourseArray.Length; x++)
{
if(CourseArray[x].CourseID == id) {return CourseArray[x];}
}
return null;
}
your array is static you could just use x < 3
and for a more c# way
using System.Linq;
public Course GetCourseByCourseID(string id)
{
return CourseArray.Where(a => a.CourseID == id).FirstOrDefault();
}
a is each course and First return the first element in the resulting collection. a pit fall with this approach is that if you have more than one Course with the same id you only get the first one.
but then that is likely a design flaw.
it should be noted that if CourseArray were to be multidimensional. then length would not be usable because it return the total number of elements in all dimensions of the array. thus using System.Linq Count() extension method would have to be used.
The simplest way would be to use a foreach loop, checking through all the courses until the ID matches. If no ID matches, the loop will exit and you should return null.
The more 'advanced' way would be to use LINQ, either straight up LINQ or the extension methods to achieve the same result but with less code.
With any language it is best to state a return variable which will start in a failure state. Then do the work of trying to find the non failure state and assign it to the return variable. If one doesn't find a non failure state, no assignment is done and the return value is correct as null.
Example:
public Course GetCourseByCourseID(string id)
{
Course foundCourse = null;
if (CourseArray != null)
{
// Check course array here for the id and if one is found, assign to foundCourse.
}
return foundCourse;
}
So within the if's you can continue to remove any possible failure situations. The one above in the if checks CourseArray for null. If it is null it gracefully exits and doesn't throw an exception about trying to check CourseArray. Keep doing 'sanity' checks where possible and it makes for better programming.

Dude, where's my object? or, Why does Linq not return my object?

Once I have the results of my Linq query, I am not always happy. There could be a result that I was expecting to be there but wasn't. For example, my client was expecting that a customer was in a customer list, but it wasn't. It is my client saying "Dude, where's my customer?", not me. I am the Dude, and to remain a dude, I have to give my client the reason.
Is there a simple way to take a given object instance and a Linq query and determine which expressions within the query excluded that instance?
Edit Ok, here is a better example
Output should be something along the lines:
Your Customer was excluded for 2 reasons:
Customer FirstName is Carl but it should be Daniel
Customer Age is 18 but it should be > 20
public class Customer
{
public string FirstName { get; set; }
public int Age { get; set; }
}
[Test]
public void Dude_wheres_my_object_test1()
{
var daniel = new Customer { FirstName = "Daniel", Age = 41 };
var carl = new Customer { FirstName = "Carl", Age= 18 };
var Customers = new List<Customer>() { daniel, carl };
// AsQueryable() to convert IEnumerable<T> to IQueryable<T> in
//the case of LinqtoObjects - only needed for this test, not
//production code where queies written for LinqToSql etc normally
//return IQueryable<T>
var query = from c in Customers.AsQueryable()
where c.Age > 20
where c.FirstName == "Daniel"
select c;
//query would return Daniel as you'd expect, but not executed here.
//However I want to explain why Carl was not in the results
string[] r = DudeWheresMyObject(query, carl);
Assert.AreEqual("Age is 18 but it should be > 20", r[0]);
Assert.AreEqual("FirstName is Carl but it should be Daniel", r[1]);
//Should even work for a Customer who is not
//in the original Customers collection...
var ficticiousCustomer = new Customer { FirstName = "Other", Age = 19};
string[] r2= DudeWheresMyObject(query,
ficticiousCustomer);
Assert.AreEqual("Age is 19 but it should be > 20", r2[0]);
Assert.AreEqual("FirstName is Other but it should be Daniel", r2[1]);
}
public string[] DudeWheresMyObject<T>(IQueryable<T> query, T instance)
{
//Do something here with the query.Expression and the instance
}
First of all, before I attempt to write some fancy Fluent framework, Has anyone done this already?
So far, I have considered navigating the expression tree and executing each branch against an IQueryable that only contains my object. Now I don't have a great deal of experience using raw expression trees, so I would like those who have to suggest any pitfalls or even explain whether this is a dead end and why.
I am anxious that anything that results from this should:
Be Reusable - Should be applicable to any object compared against a Linq query returning objects of the same class.
Not affect the performance of the original query (this should just be standard Linq).
Should be Linq-implementation agnostic.
If there are multiple property values set on the missing instance that excluded it from the results, then all of those reasons should be reported.
Edit
I am not suggesting that I keep executing LinqToSql against the database multiple times with different permutations of the query and comparing the results. Rather, I am looking for a way to take a single instance and compare it to the expression tree (without executing the query directly again)
Also, I would like an indication of whether others might find this useful. If so, I would consider starting an open source project to solve it.
I think you'd have to re-create the query as linq-to-objects and deal with the subtle differences between linq-to-sql/entities/whatever and linq-to-objects, accepting that some providers just won't work realistically.
You have your object you want to find in an in memory IEnumerable<T> or something.
You'd have to walk the expression tree somehow and snip out the leaves, so say you had:
where obj.foo == true && obj.bar == "yes"
you'd have to figure out that obj.foo == true and obj.bar == "yes" are leaves and start there. It'd be a sort of depth first search of the expression tree.
So, construct linq to objects queries that only had those leaves. See if the object is included in the results. If not then we've found out why it's excluded, if not then go up the tree (i.e. make the where query include more clauses, getting closer to the orignal one until the object disappears from the results).
As I see it the tough parts would be handling the differences between original linq to 'whatever' and link to objects, figuring out where to split the where claues, dealing with things like joins which can also exclude things and dealing with things like SqlMethods.Like that don't work in linq to objects.
For a one-off exploration of what's filtering out the result, it's hard to beat the Dump method in LINQPad. Here's an extract from one of their samples that shows it in action:
// Dump returns exactly what it was given, so you can sneakily inject
// a Dump (or even many Dumps) *within* an expression. This is useful
// for monitoring a query as it progresses:
new[] { 11, 5, 17, 7, 13 } .Dump ("Prime numbers")
.Where (n => n > 10) .Dump ("Prime numbers > 10")
.OrderBy (n => n) .Dump ("Prime numbers > 10 sorted")
.Select (n => n * 10) .Dump ("Prime numbers > 10 sorted, times 10!");
This gives nicely formatted tables of results:
With some fun expression hacking, you can see the results of each stage of the evaluation for each item in the set. Inspect the local result after the breakpoint has been hit to see the results of the evaluation. To actually use the results of the evaluation, just append .Where(x => x.IsIncludedInResult).Select(x => x.EvaluationTarget) to the line where the report is generated.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
namespace ConsoleApplication4
{
[DebuggerDisplay("{Condition} on {EvaluationTarget} is {EvaluationResult}")]
public class ReportItem<T>
{
public string Condition { get; private set; }
public IEnumerable<ReportItem<T>> NestedReports { get; private set; }
public object EvaluationResult { get; private set; }
public T EvaluationTarget { get; private set; }
public ReportItem(Expression condition, IEnumerable<ReportItem<T>> nestedReports, T evaluationTarget, object evaluationResult)
{
Condition = condition.ToString();
NestedReports = nestedReports;
EvaluationTarget = evaluationTarget;
EvaluationResult = evaluationResult;
}
public override string ToString()
{
return string.Format("{0} on {1} is {2}", Condition, EvaluationTarget, EvaluationResult);
}
}
[DebuggerDisplay("Included: {IsIncludedInResult} \n{Summary}")]
public class Report<T>
{
public ReportItem<T> Contents { get; private set; }
public T EvaluationTarget { get; private set; }
public Report(T source, Expression<Func<T, bool>> predicate)
{
EvaluationTarget = source;
IsIncludedInResult = predicate.Compile()(source);
Contents = Recurse(predicate.Parameters.Single(), predicate.Body, source);
}
private object Evaluate(Expression expression, ParameterExpression parameter, T source)
{
var expr = Expression.Lambda(expression, parameter);
var #delegate = expr.Compile();
var value = #delegate.DynamicInvoke(source);
return value;
}
private ReportItem<T> Recurse(ParameterExpression parameter, Expression sourceExpression, T source)
{
var constantExpression = sourceExpression as ConstantExpression;
if(constantExpression != null)
{
return new ReportItem<T>(sourceExpression, null, source, Evaluate(constantExpression, parameter, source));
}
var unaryExpression = sourceExpression as UnaryExpression;
if(unaryExpression != null)
{
var content = Recurse(parameter, unaryExpression.Operand, source);
var result = Evaluate(sourceExpression, parameter, source);
return new ReportItem<T>(sourceExpression, new[]{content}, source, result);
}
var binaryExpression = sourceExpression as BinaryExpression;
if(binaryExpression != null)
{
var left = Recurse(parameter, binaryExpression.Left, source);
var right = Recurse(parameter, binaryExpression.Right, source);
var item = new ReportItem<T>(sourceExpression, new[] {left, right}, source, Evaluate(sourceExpression, parameter, source));
return item;
}
var methodCallExpression = sourceExpression as MethodCallExpression;
if(methodCallExpression != null)
{
var args = methodCallExpression.Arguments.Select(x => Evaluate(x, parameter, source)).ToArray();
var result = methodCallExpression.Method.Invoke(Expression.Lambda(methodCallExpression.Object, parameter).Compile().DynamicInvoke(source), args);
return new ReportItem<T>(sourceExpression, null, source, result);
}
throw new Exception("Unhandled expression type " + sourceExpression.NodeType + " encountered");
}
public bool IsIncludedInResult { get; private set; }
public string Summary
{
get { return Contents.ToString(); }
}
public override string ToString()
{
return Summary;
}
}
public static class PredicateRunner
{
public static IEnumerable<Report<T>> Report<T>(this IEnumerable<T> set, Expression<Func<T, bool>> predicate)
{
return set.Select(x => new Report<T>(x, predicate));
}
}
class MyItem
{
public string Name { get; set; }
public int Value { get; set; }
public override int GetHashCode()
{
return Value % 2;
}
public override string ToString()
{
return string.Format("Name: \"{0}\" Value: {1}", Name, Value);
}
}
class Program
{
static void Main()
{
var items = new MyItem[3];
items[0] = new MyItem
{
Name = "Hello",
Value = 1
};
items[1] = new MyItem
{
Name = "Hello There",
Value = 2
};
items[2] = new MyItem
{
Name = "There",
Value = 3
};
var result = items.Report(x => !x.Name.Contains("Hello") && x.GetHashCode() == 1).ToList();
Debugger.Break();
}
}
}
It's kind of a tricky one, as in, from your example you could always code something to check for specifics and report 'I searched for term x and the object i returned was not in term x'.
I would have though as others suggested though, that this would have been along the lines for 'return me x' then in code, run a query for 'x where x.property = y' and report non matches.
Following this through, I'd imagine the issue would be that in order to generate the list of non matches, your query or object graph would become pretty massive as you'd need your original object either initially include (or to be expanded via lazy loading to include) many permutations to determine the matches or not.
This is kind of the inverse of running a query on the first place where you'd start with an object and sub select based on conditions, you'd want to select and then selectively super select, catching non conditions.
It's an interesting problem, and one that I'd normally address either client side or code wise before getting to a point where and object was returned or not. But I guess the perfect solution would be to return a single solution and perhaps examine it's associations for links.
The links wouldn't be too hard to find a generic "I've not got one of these" type reason, but to give a 'I've got this link, not that link' response would be harder.
You'd need to maybe provide a method based on some form of predicate builder which took a field and search term and returned an appropriate message if things didn't match. In my mind seems like two slightly different problems.
Slightly rambling now, but would be curious to hear any answers to this!...
I think I follow what you mean. What I think you would want to do is perform two queries, one with selection criteria, and one without, then perform a Linq Except on them to determine which items were excluded, then walk that list and determine what criteria caused them to be excluded.
I can't really think of a better way to do it.
Something like this:
var a = db.Trades.Where(z => z.user == x && z.date == y);
var b = a.Where(z => z.TradeCurrency != null && z.TradeUnderlying.Index != null);
var c = a.Except(b);
List<string> reasons;
foreach(var d in c) {
if (d.TradeCurrency == null)
// add reason
... etc..
}
This would perform a single query (which would have several sub-queries) and only return the results that were excluded (rather than trying to return all results which could be quite large). Unless of course you have a million excluded records and only a few included ones.
Not sure how efficient this is, though compared to a way I can't think of.
EDIT:
I think you are forgetting that Linq queries do not execute until you call an operation that realizes them. In this example, the database is only hit once, even though there are several linq query objects here. The expression tree is modified without executing the queries.
So in this example, when the foreach() occurs, a single database query (with several sub-queries) is executed.

Updating the original reference to an object that was returned from a linq query

I would like to do something like this:
[HttpPost]
public JsonResult Submit(Person UpdatedPerson)
{
//Find the original Person that the model was bound against
//Update the collection's reference to reflect the changes
//from the posted model version
Person original = PersonCollection
.SingleOrDefault(p=>p.Id == UpdatedPerson.Id);
if(original!=null)
{
//update the value from PersonCollection
//doesn't work, of course
original = UpdatedPerson;
}
}
I'm currently doing this:
[HttpPost]
public JsonResult Submit(Person UpdatedPerson)
{
//Find the index into PersonCollection for the original
//model bound object, use the index to directly mutate the
//PersonCollection collection
int refIndex = -1;
for(int i=0;i<PersonCollection.Length;i++)
{
if(PersonCollection[i].Id == UpdatedPerson.Id)
{
refIndex = i;
break;
}
}
if(refIndex >= 0)
{
PersonCollection[refIndex] = UpdatedPerson;
}
}
It feels like I'm missing something simple here, it shouldn't be so much trouble to accomplish what I'm after.
What is the best practice way to do this sort of stuff?
When you do this:
original = UpdatedPerson;
you are just assigning the reference to original, thus original now points to the same object that UpdatedPerson points to. and that is why you are losing the reference value for the object that you have retrieved from the collection.
Try assigning the individual fields instead.
In your first example, you make a variable declaration:
Person original;
That original variable is a reference.
Then you assign it to some item in your list
Then later you make a call like this:
original = UpdatedPerson;
In this call, you're updating the variable reference, not anything from the collection.
What you might want to do is something like this (Presuming Person is a class, not a struct):
original.UpdateValuesToMatch(UpdatedPerson);
but you'd have to create such a method on the person object.
Or in your second method, you could simplify from:
if(PersonCollection[i].Id == UpdatedPerson.Id)
{
refIndex = i;
break;
}
}
if(refIndex >= 0)
{
PersonCollection[refIndex] = UpdatedPerson;
}
to
if(PersonCollection[i].Id == UpdatedPerson.Id)
{
PersonCollection[i] = UpdatedPerson;
break;
}
}
Description
You can use FindIndex
Sample
[HttpPost]
public JsonResult Submit(Person UpdatedPerson)
{
//Find the index into PersonCollection for the original
//model bound object, use the index to directly mutate the
//PersonCollection collection
int refIndex = PersonCollection.FindIndex(x => x.Id == UpdatedPerson.Id);
if (refIndex != -1)
PersonCollection[refIndex] = UpdatedPerson;
}
More Information
List.FindIndex Method

Code structure, a methods should only do one thing

I am having a bit following the "a method should only do one thing"
I have a car text file, and if it contains even one BMW I want to set isValid to true, but while I am going through the text file anyways I thought I would also populate two list high end models(M3,M5 etc) and lower model (335, X3 etc).
I know that method should only do one thing, but it seems so convenient for it to also populate the lists. Here is what I have:
private bool hasBMWegments()
{
foreach (ClassLib.CarSegment carElement in CarSegmentFactory.ContainsCar("BMW"))
{
isValid = true;
if (carElement.Class.IndexOfAny(lowerModels) == 0)
{
lstOlderSegment.Add(carElement.ElementNumber);
}
if (carElementClass.IndexOfAny(upperModels) == 0)
{
lstNewerSegment.Add(carElement.ElementNumber);
}
}
return isValid;
}
Should I just create a method that performs the foreach check again? Or should I create another method inside that method (I would think that would be messy, and wouldn't related to the method name)
edit: sorry working with framework 2.0
I find that code to be a mess compared to this:
private IEnumerable<ClassLib.CarSegment>
GetModels(IEnumerable<ClassLib.CarSegment> segments, string modelID)
{
return segments.Where(x => x.Class.IndexOfAny(modelID) == 0);
}
// ...
var bmwSegments = CarSegmentFactory.ContainsCar("BMW").ToArray();
bool isValid = bmwSegments.Any();
var olderModelSegments = GetModels(bmwSegments, lowerModels);
var newerModelSegments = GetModels(bmwSegments, upperModels);
This code is obviously correct at a glance. The other code makes you look twice at the loop to figure out what's going on.
It looks like all you're doing is setting isValid to true on the first pass through the foreach. So all isValid really means is "is there at least one element?".
In which case you do not need to iterate twice. You can use Any() to do the valid check:
bool IsValid(IEnumerable<CarSegment> elements)
{
return elements.Any();
}
void PopulateSegments(IEnumerable<CarSegment> elements)
{
foreach(var element in elements)
{
//add to lists
}
}

Categories

Resources