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.
Related
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#.
I'm looking to give a talk about LINQ, and wanted to mention how querying collections used to work. Back in .Net 1.1, I seem to remember there being a method (Find() maybe?) where you would pass the address of another method which would interrogate each item in the collection and determine whether it should be included in the filtered collection.
Am I completely misremembering this? It stuck with me, as the syntax was unusual for the time.
I thought it was something like:
public bool ContainsFoo(string term){
if(term.contains("Foo"){
return true;
}
return false;
}
And you could call it like:
filteredCollection = collection.Find(ContainsFoo);
I seem to remember a lot of people commenting on how LINQ was so much faster to code because developers could now write functions in-line. How were we writing functions "out-line" previously?
Before LINQ you were just limited to all the built-in List/List<T> methods, and yes Find is one of them (still is). The difference is it expects a Predicate<T> as opposed to a Func<Boolean, T> which you can still do inline e.g.
var found = list.Find(delegate(Item item) { return item != null; });
Or as you demonstrated by using a named method.
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.
At the moment I use the following procedure to determine if a list has elements:
if (aList.Count > 0)
{
//doStuff
}
I'm asking myself if there is a more elegant way to find out if there are elements, without using a comparison.
Count is the best option - it is a property of List<> meaning that access time is O(1).
It is also descriptive.
You can use linq:
if (aList.Any())
{
//doStuff
}
I suppose if it's the wording that bothers you and you want a more expressive way to describe it, you could write a custom extension method:
public static bool HasItems(this IList<T> list)
{
return list.Count > 0;
}
Then you'd use it like this:
if (aList.HasItems())
{
//doStuff
}
It's a matter of personal preference, really. The term HasItems may, for example, sound more intuitive than Count > 0 and may even look a little cleaner (again, subjectively).
However, what I personally don't like about it is that it's a method rather than a property. (I personally would love if C# added support for "extension properties.") There are exceptions, but to me intuitively I expect a property to just give me information on the state of something (hopefully in O(1) time as Oded mentions), whereas I would expect a method to "do something" and have some sort of side-effect on the state of the object.
Again, it's all a matter of personal preference. Just an option that's available to you.
you can write extension method as below
public static Boolean IsEmpty<T>(this IEnumerable<T> sourceList)
{
return (sourceList==null) ? true : !sourceList.Any();
}
see this question for more info - Checking if a list is empty with LINQ
This is already a most elegant solution.
Can use (just an example) Count(x=>x..condition..); linq type to find out the count of the elements sutisfying some specified condition.
I wrapped this check in an extension (Null checking AND checking for items is cumbersome imo)
public static bool IsAny<T>(this IEnumerable<T> item)
{
return item != null && item.Any();
}
// Usage
listOfFoo.IsAny()
I have the following recursive function that is used to search down a hierarchical tree and remove found objects from a list:
private List<Tag> RemoveInvalidTags(Device device, List<Tag> tags)
{
var childDevices = device.ChildDevices.Select(c => c.ChildDevice);
foreach (var child in childDevices)
{
tags.Remove(child.Tag);
RemoveInvalidTags(child, tags);
}
return tags;
}
What I am expecting this to do is remove all child device tags at this level from the tags list, call the function recursively for your children, then return that list up to the previous level.
Will this pass the tags list by reference and modify the original passed list? Or should I be doing something along the lines of
validTags = CollectValidTags(child, tags);
and adding up all the returned lists?
Will this pass the tags list by reference
No. The list object is passed "by value" (but see next). (ref or out is required to "pass by reference" in C#, but that is not being done here, nor does it need to be.)
and modify the original passed list?
Yes. This is because the list object is passed. And that list object is mutated. Passing a reference type (anything defined with class) never implicitly makes a copy/clone/duplicate. An object is what it is.
Now, back to "pass by value": the "value passed" is the value of the "reference" (internal, no need to concern with this): this calling strategy is better known as Call/Pass By Object Sharing in a langauge like C#. The same object is shared (just as if it were assigned to two different variables). (Value types -- a struct -- are different in that they (often) are copied/duplicated on the stack, but a List<T> is a class.)
Or should I be doing something along the lines of
It depends upon the desired semantics. Is the caller expecting the side-effects directly or indirectly? Can the mutation side-effect lead to unexpected scenarios? Make sure to document it either way. (I prefer the way that guarantees the initial object is not mutated.)
Hope that clears some things up.
Happy coding.
In your code you are modifying the items in your tags parameter and passing back the modified list as your result. You want to avoid modifying lists in this way - especially inside loops where it can cause you grief in many situations.
I have a LINQ-based alternative for you.
If I understand the intent of your code you want to do something like this:
Func<Device, IEnumerable<Device>> flatten = null;
flatten = d =>
{
return (new [] { d }).Concat(
from c in d.ChildDevices
from f in flatten(c)
select f);
};
var collectedValidTags = flatten(device).Select(d => d.Tag);
var result = tags.Except(collectedValidTags).ToList();
This approach doesn't pass your list of tags around so there is no chance of modifying your original list.
Does this help?
Short answer - your code will do what you want.
Long answer - you should read descriptions of what the ref keyword does. I would suggest you read as many descriptions as possible; there are many different ways to articulate it ("I like to think of it as... ") and some will work for you whilst others won't. If you read many descriptions (from people who understand it) then some kind of understanding should gel for you.
Here's a list to get you started:
Use of 'ref' keyword in C# (my answer)
C# ref keyword usage
Passing by ref?
Example of practical of "ref" use