foreach loop with a where clause - c#

I was wondering if it's possible to create a foreach loop in C# with a where loop. Not with a if statement inside, but and where clause in the declaring of the loop.
Maybe something like this?
foreach(var n in people where n.sex == male)
{
}

Yes, it is possible:
Method Syntax:
foreach (var person in people.Where(n => n.sex == "male"))
{
}
Or the rather lengthy Query Syntax:
foreach (var person in from person in people where person.sex == "male" select person)

It looks like what you need is a lambda expression to limit the items the foreach look works with.
Based on your limited example, something like this:
foreach(var n in people.Where(n => n.sex == male))
{
}

As Yuval's answer and its comments point out, you can put any query -- in either "fluent" or "query syntax" form -- as the collection expression. This leads to awkward constructions like:
foreach(var person in from person in people where person.sex == male select person)
Not only is this very verbose, in the example I have given here the simple name person is used both in the query and the loop declaration. You might wonder why that is even legal, as normally C# is strict about ensuring that a simple name has only one meaning in a given local variable scope. The answer is here: http://ericlippert.com/2009/11/05/simple-names-are-not-so-simple-part-two/
IIRC the C# design team briefly considered a syntax such as you describe, but never got even as far as writing a specification. It's a nice idea but it just wasn't a sufficiently awesome language extension to make it to the top of the list. This would be a nice feature to pitch for a future version of C#.

Related

C# How to Access a Specific Index of a List of classes

I have created a class called studentRecord, and it contains several properties such as Student Number, First Name, Last Name, Courses, and Credit Hours for keeping track of individual student records. I also have created a list called List<studentRecord> lstRecords = new List<studentRecord>(); that stores the various objects (students).
I understand adding a student object through using lstRecords.Add();, but am running in to trouble with editing the objects. The user is supposed to be able to enter a student number, and then be able to access and edit the properties of that specific instance of the object. I have come up with this code:
StudentRecord editRecord = lstRecords.Find(indexRecord =>
indexRecord.intStudentNumber == intChosenRecord);
(By the way, intChosenRecord is a variable I declared to keep track of which index they are looking for)
I understand that StudentRecord is declaring a new object of that type, and that editRecord is my new object's name. However, I run into problems with using the .Find() method. I realize that .Find() searches through the list to find something that matches up with in input. Therefore, I assume that the intChosenRecord is what the program is searching for.
However, I have no idea what indexRecord is! This is the only time that it is used within the code, and I can change it to any name I want without errors. Could someone explain what this code does, and what indexRecord is?
"indexRecord" is a variable which correspond to each student in the list.
"Find" stops and returns the current student once condition (or "predicate") at the right of "=>" is true.
Therefore you can name it as you want, as long as you use the same name at left and right of "=>"
A similar loop could be :
StudentRecord editRecord = null;
foreach(var indexRecord in lstRecords)
{
if(indexRecord.intStudentNumber == intChosenRecord))
{
editRecord = indexRecord;
break; // Exits the loop.
}
}
This code is not very clean, but I give it for the sake of clarity, since it does the same than yours with an "oldschool" loop, which is certainly more familiar for you.
See http://msdn.microsoft.com/fr-fr/library/bb397687.aspx for more details on this syntax.
And http://msdn.microsoft.com/fr-fr/library/bb397926.aspx for other methods than "Find".
indexRecord is the argument of the lambda expression. It can have any name you want. In your case, it represent a StudentRecord (an element of your list)
you can easily change your code by :
StudentRecord editRecord = lstRecords.Find(x => x.intStudentNumber == intChosenRecord);
You can learn more about lambda expression on many site, as http://www.dotnetperls.com/lambda
The variable editRecord refers to the match returned by Find(), so it's not creating a new object or new instance of anything; it's referring to an existing instance.
Think of indexRecord as an identifier used to iterate over all the items in a collection, like when you say:
var numbers = new List<int>();
foreach (var n in numbers)
{
// do something with n
}
You can replace n, or indexRecord, with any identifier you like.
When you are using "=>", you are using a lambda expression.
In your case, "indexRecord" is the variable name of the input parameter for your lambda expression "indexRecord.intStudentNumber == intChosenRecord". And indexRecord correspond to a student stored in your list.
I would suggest that you get familiar with the lambda expressions, because it is a powerful and common used feature of c#.
try this ..
List<int> idlist=lstRecords.select(t=>t.intStudentNumber).toList();
int index=idlist.indexof(intChosenRecord);
studentRecord record=lstRecords[index];
i always use this ...

Generalizing constructors to operate on arrays in C#

I wanted to know how to apply a constructor on each element of an array that would then return an array of constructed objects. Specifically, I am working with C#'s TreeNode.
The concept I want is as follows:
string[] animals = {"dog","cat","mouse"};
TreeNode[] animalNodes = TreeNode[](animals);
Where TreeNode[](animals) would have the cumulative effect of
animalNodes[0] = TreeNode("dog");
animalNodes[1] = TreeNode("cat");
animalNodes[2] = TreeNode("mouse");
I know I can us foreach and load such a structure manually but if possible, I'm looking for the elegant 'one line' way. I have looked long and hard for how to do this but could not find anything.
Some LINQ will do the trick:
TreeNode[] animalNodes = animals.Select(a => new TreeNode(a)).ToArray();
The Select extension method executes the specified delegate (specified via a lambda here) on each member of the list, and creates a list of the results (IEnumerable<TreeNode> in this case). The ToArray extension method is then used to create an array from the result.
Alternatively, you can use LINQ's query syntax:
TreeNode[] animalNodes = (from a in animals select new TreeNode(a)).ToArray();
The code generated by the compiler is the same for both these examples.
This is a different syntax that will give the same result like the other correct answer you already got.
TreeNode[] animalNodes = (from animal in animals select new TreeNode(animal)).ToArray();
While the other answers may work, I propose the following alternative.
My main reason for doing so is that the other examples require you to actually make the code look a little bit more complicated, and it's clear that you're looking to clean up your code, and make the assignment look and be more simple. This solution will also help you if you're going to be creating these TreeNodes in different places in your app (the other solutions would require you to copy and paste the assignment code to each place you're creating the TreeNode arrays.
The cost of having your assignment code cleaner, is moving the mess somewhere else (but honestly not really much of a mess, since it's all really straight-forward)
First, create a class to build the TreeNode array for you
public static class TreeNodeBuilder
{
public static TreeNode[] FromStringArray(String[] array)
{
TreeNode[] returnValue = new TreeNode[array.Length];
for(int i = 0; i < array.Length; i++)
{
returnValue[i] = new TreeNode(array[i]);
}
return returnValue;
}
}
And then in your assignment code, you can use the following:
String[] animals = {"dog", "cat", "mouse"};
TreeNode[] animalNodes = TreeNodeBuilder.FromStringArray(animals);
Conclusion
This (IMHO) is a better option than using LINQ as the other answers provide, mostly for code clarity, maintainability, and the separation you can achieve by putting all of this logic in a different file (a file like TreeNodeBuilder.cs).
For what it is worth you could also use the LINQ code provided in the other answers inside the above FromStringArray function (if you wanted to get the best of both worlds).
Anyways, my two cents :) Hope you find it helpful.

Multiple Selection in ForEach Extension Method

Is it possible to select multiple entiies in ForEach Extension Method?
(i.e)
partial code is given
DataTableA.AsEnumerable().ToList().
ForEach(x=>
{
x.SetField<string>("Name","Jon Skeet"),
x.SetField<string>("msg","welcome")
});
when i apply multiple selection in ForEach
x=>
{
x.SetField<string>("Name","Jon Skeet"),
x.SetField<string>("msg","welcome")
}
I am unable to complete the statement.Help Please.
You need to make the lambda compile to valid C#:
DataTableA.AsEnumerable().ToList().ForEach(
x=>
{
x.SetField<string>("Name","Jon Skeet");
x.SetField<string>("msg","welcome");
});
That being said, I'd caution against this. Using ForEach is purposely causing side-effects, and it's really not more concise than the foreach statement in the language itself. Personally, I'd just write:
foreach(var element in DataTableA.AsEnumerable())
{
element.SetField<string>("Name","Jon Skeet");
element.SetField<string>("msg","welcome");
}
This, in my opinion, is much more clear than the first statement (and shorter, and more efficient, since it doesn't force a full enumeration into the list, and a second enumeration of the list elements).

Check for Existence of a Result in Linq-to-xml

I'm using Linq-to-XML to do a simple "is this user registered" check (no security here, just making a list of registered users for a desktop app). How do I handle the result from a query like this:
var people = from person in currentDoc.Descendants("Users")
where (string)person.Element("User") == searchBox.Text
select person;
I understand the most common way to use the result would be something like
foreach (var line in people){
//do something here
}
but what do you do if person comes back empty, which is what would happen if the person isn't registered?
I've looked around on this site and on MSDN and haven't found a really clear answer yet.
Extra credit: Give a good explanation of what people contains.
I've read that it's better to use Any() rather than Count()==0 in these situations. E.g
bool anyPeople = people.Any();
if (anyPeople) {
See http://rapidapplicationdevelopment.blogspot.com/2009/07/ienumerablecount-is-code-smell.html for more discussion on the performance impact of using Count() with Linq, especially with IEnumerable, where the entire collection is iterated by the Count() method.
Also using Any() arguably is a clearer explanation of your intent that Count()
Try using:
from person in currentDoc.Descendants("Users")
where (string)person.Element("User") == searchBox.Text && !person.IsEmpty
select person;
The above will select only non-empty person elements. There is also a HasElements property that says whether or not it has any child elements - this may be better to use depending on your XML structure, as blank space make make IsEmpty return false (blank space can count as text).
The people variable is going to be an IEnumerable<XElement> variable, as you appear to be querying a collection of XElement. The var keyword is simply a shortcut to allow it the variable to be typed by the compiler, so you didn't need to figure out the type beforehand and use List<XElement> people = ...
You could just do a people.Count() and if you get 0, you know that person is not registered.
As told by Matt use Count()==0 or Any().
people is IEnumerable<XElement> I think.

How do you use the var keyword? [duplicate]

This question already has answers here:
Closed 13 years ago.
Duplicate
Use of var keyword in C#
C# - Do you use "var"?
Should I always favour implictly typed local variables in C# 3.0?
Would you prefer to write your code like this:
var myVar = new MyClass();
or
MyClass myVar = new MyClass();
I don't object to use the var keyword in example above; however, in the code below I don't like the usage of var.
var files = Files.GetFiles();
In this example it's not obvious what type variable files is going to be.
What's your preference for using the var keyword?
I tend to use 'var' in places where I, reading the sourcecode, can infer the type of the variable without having to navigate to other places in the sourcecode.
For example, any time I new up an object:
var c = new Customer();
Or when calling a method in which the return type is clear:
var c = Customers.GetCustomerByID(5);
Also, 'var' must be used in the case of anonymous types:
var t = new { Key = "One", Value = 1 };
And I also use it with LINQ of course:
var q = from c in Customers
where c.CustomerID == 5
select c;
In the case above 'q' is of type IQueryable (assuming Customers is an enumeration of Customer objects).
Also 'foreach' statements as well - GREAT please to use 'var':
foreach (var i in intArray) { /* use i */ }
Other examples abound I'm sure - but these cover my most frequent use cases.
If it's a situation where either would work (which excludes the anonymous type situation), I try to use whatever will make the code easier to understand in the future. Sometimes that means using var if the usage scope is small or the type being assigned to is unwieldy (e.g., somekind of nested generic) to repeat and adds clutter. I also tend to use var where most people expect to see (e.g. as the declaration of a linq query).
I think it's best to only use var when creating a new object (with new) and with LINQ (of course). That makes the code much easier to understand, IMHO.
I use it everywhere I can. I think it makes code far more clean and readable. (Who am I kidding? I just do what resharper tells me to do :)
Much more of that on this SO thread.

Categories