Can anybody explain why I don't see the (my) expected output for the WriteLine?
I can see it when I'm debugging it in VS and refresh the 'result' to see its content in my Local window inside VS.
THX
Func<Category, bool> del = (Category cat) => {
System.Console.WriteLine(cat.CategoryName);
return cat.CategoryID > 1;
};
NorthwindEntities nw = new NorthwindEntities();
var result = nw.Categories.Where<Category>(del);
Console.Read();
LINQ structures are lazy-evaluated, which means that your lambda function will not be invoked until items are requested from the enumeration (and even then, not necessarily all at once). This should cause the values to be output to the console:
var result = nw.Categories.Where<Category>(del).ToList();
Please note the implications here: if you did this, the values would be output to the console twice:
var result = nw.Categories.Where<Category>(del);
var otherVariable = result.ToList();
foreach(var item in result)
{
// do something
}
This is a good reason why you should avoid involving code with side-effects in your LINQ queries.
You need to do something with results in order for your lambda to exeucute. Try this:
var result = nw.Categories.Where<Category>(del);
foreach(var r in result)
{
}
As you enumerate over result your lambda will be called.
Perhaps you need to materialize the query. You result is an IEnumerable, so the delegate will file only when the result is actually enumerated.
Try this: var result = nw.Categories.Where<Category>(del).ToList();
This is due to lazy evaluation. The function hasn't actually been executed yet, so it isn't enumerated until you either enumerate it yourself or you do something like this:
Category[] categories = nw.Categories.Where<Category>(del).ToArray();
Calling this will invoke the evaluation. You can read up about this on the web but here is an article to kick things off.
Related
I have the following code:
foreach (var b in userNames.Select(a => new User()))
{
...
}
This works quite well, since it gives me all "fresh" user objects, however Code Analysis complains that I shouldn't create unused locals, so my question is, is there a way of ignoring the arguments (similar to the "_" in Haskell).
PS: prehaps my example is not the best. I am sorry for this.
Thanks!
Update 1
I got the following code analysis error:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "a"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "b")]
_ is a perfectly valid variable name in C#. So writing
foreach(var b in userNames.Select(_ => new User()))
{
}
is perfectly valid code. It depends on your analysis rules whether it accepts such cases or not.
However, your code is indeed quite suspicious: you're mapping a collection of user names to a collection of users but you're not specifying a direct relation between the two: maybe you wanted to write something like this:
foreach(var b in userNames.Select(username => new User(username)))
To create a collection of objects of a given size, just use the length from the original collection.
var newColletion = Enumerable.Repeat(false, input.Length)
.Select(_ => new User());
but perhaps better would be your own helper method
static class MyEnumerable {
IEnumberable<T> Repeat<T>(Func<T> generator, int count) {
for (var i = 0; i < count; ++i) {
yield return generator();
}
}
}
and then use
var newCollection = MyEnumerable.Repeat(() => new User(), oldCollection.Length);
If quantity is your concern, and need linq, rewrite it as
foreach(var user in Enumerable.Repeat(()=>new User(),Usernames.Count).Select(x=>x()))
{
}
But, it may look ugly based on how you see it.
I'm sure there is a valid case where you would want to ignore arguments like this, but this doesn't seem like one of them. If you are creating N User objects for N userNames, surely you want to couple those together?
foreach (var b in userNames.Select(a => new { name = a, user = new User() }))
{
...
}
Then you won't have any unused arguments.
But the question remains why you aren't just doing this:
foreach (var name in userNames)
{
var user = new User();
// ...
}
As far as I can see, your use of .Select() makes no sense here.
Select performs a projection on the collection on which it is called, performing a specified operation on each element and returning the transformed results in another collection. If you do not need to perform any operation on the lambda element, you'd better simply create an array of User objects directly.
Answering your edit, as I said above, you can simply do this:
var NewColl = new User[userNames.Length];
As for initialization, you could have done this:
Enumerable.Repeat<User>(new User(), userNames.Length);
I want to invoke Queryable.Where() and get all elements. There's no version of Where() that works without a predicate function. So I have to right this:
var result = table.Where( x => true );
and it works but that feels really stupid to me - x is never used, and there's no "transformation" for the => "arrow" symbol.
Is there a more elegant solution?
You can use the following, which is more elegant:
var result = table;
You could also omit result completely, and use table directly.
Isn't table.Where(x=>true) essentially a noop? I mean, what is the point? You can do use _ instead of x though, which is idiomatic.
table.Where(_=> true);
But really, the following is what you are doing:
for (var item in table)
{
if (true) // your Where() clause..
{
yield item;
}
}
See how it doesn't really make sense?
table.Where( x => true ) is not "returning all elements". It simply returns an enumerable that has enough information to return some subset of elements when it is being enumerated upon. Until you enumerate it, no elements are "returned".
And since this subset is not even proper in this case (i.e. all elements are returned), this is essentially a no-op.
To enumerate over all elements, write a simple foreach, or use ToList or ToArray or if you don't care about actually returning any elements (and just want to enumerate, presumably for side-effects): table.All(x => true) or table.Any(x => false), or even just table.Count().
In this case you would not need to call Where because you are not filtering the Queryable.
If you still wish to call Where and you do this in many places you could define a static Func and reuse that:
public static Func<int, bool> t = ReturnTrue;
public static bool ReturnTrue(int i)
{
return true;
}
table.Where(t);
If you're trying to get a copy of the contents of table instead of a reference,
var result = table.ToList();
but it's not clear if that's really what you're trying to accomplish. Details?
I had a strange bug i don't understand, and changing LINQ's IEnumerable to list half way through fixed it, and i dont understand why
Not Real the Code, but very similar
The code below doesn't work:
// an IEnumerable of some object (Clasess) internally an array
var ansestors = GetAnsestors();
var current = GetCurrentServerNode();
var result = from serverNode in ansestors
select new PolicyResult
{
//Some irrelevant stuff
OnNotAvailableNode = NodeProcessingActionEnum.ContinueExecution,
};
var thisNode = new PolicyResult
{
//Some irrelevant stuff
OnNotAvailableNode = NodeProcessingActionEnum.ThrowException,
};
result = result.Reverse();
result = result.Concat(new List<PolicyResult> { thisNode });
result.First().OnNotAvailableNode = NodeProcessingActionEnum.ThrowException;
// When looking in the debugger, and in logs, the first element of the
// result sequence has OnNotAvailableNode set to ContinueExecution
// Which doesnt make any sense...
But when i change the ending to the following it works:
result = result.Reverse();
result = result.Concat(new List<PolicyResult> { thisNode });
var policyResults = result.ToList();
var firstPolicyResult = policyResults.First();
firstPolicyResult.OnNotAvailableNode = NodeProcessingActionEnum.ThrowException;
return policyResults;
All the types here are classes (reference types) except NodeProcessingActionEnum which is an enum.
Is this a bug?
Me missing something crucial about LINQ?
Help?
result.First() executes the (deferred / lazy) query.
That line will set the value OK but when you use result later the query will be executed again.
Later you are looking at a newly fetched copy. The fact that it is different lets me assume that GetAnsestors() is also lazily evaluated and is not an in memory List<>
This means that ToList() is a worthwhile optimization as well as a fix. Note that after the ToList you can also use
var firstPolicyResult = policyResults[0];
The problem is that running First on your IEnumerable removes it from the enumerator so you've then checking the next element. Actually I've changed my mind - that's probably not it. This solution might be worth a shot, though.
You could wrap the IEnumerable with something which makes the change for you, e.g. using the Select override which accepts an index too:
var modifiedResults = results.Select((r, index) => {
if (index == 0) {
// This is the first element
r.OnNotAvailableNode = NodeProcessingActionEnum.ThrowException;
}
return r;
});
(untested) should do the trick.
It's been a while since I've used lambda expressions or LINQ and am wondering how I would do the following (I know I can use a foreach loop, this is just out of curiosity) using both methods.
I have an array of string paths (does it make a difference if it's an array or list here?) from which I want to return a new list of just the filenames.
i.e. using a foreach loop it would be:
string[] paths = getPaths();
List<string> listToReturn = new List<string>();
foreach (string path in paths)
{
listToReturn.add(Path.GetFileName(path));
}
return listToReturn;
How would I do the same thing with both lambda and LINQ?
EDIT: In my case, I'm using the returned list as an ItemsSource for a ListBox (WPF) so I'm assuming it's going to need to be a list as opposed to an IEnumerable?
Your main tool would be the .Select() method.
string[] paths = getPaths();
var fileNames = paths.Select(p => Path.GetFileName(p));
does it make a difference if it's an array or list here?
No, an array also implements IEnumerable<T>
Note that this minimal approach involves deferred execution, meaning that fileNames is an IEnumerable<string> and only starts iterating over the source array when you get elements from it.
If you want a List (to be safe), use
string[] paths = getPaths();
var fileNames = paths.Select(p => Path.GetFileName(p)).ToList();
But when there are many files you might want to go the opposite direction (get the results interleaved, faster) by also using a deferred execution source:
var filePaths = Directory.EnumerateFiles(...); // requires Fx4
var fileNames = filePaths.Select(p => Path.GetFileName(p));
It depends on what you want to do next with fileNames.
I think by "LINQ" you really mean "a query expression" but:
// Query expression
var listToReturn = (from path in paths
select Path.GetFileName(path)).ToList();
// Extension methods and a lambda
var listToReturn = paths.Select(path => Path.GetFileName(path))
.ToList();
// Extension methods and a method group conversion
var listToReturn = paths.Select(Path.GetFileName)
.ToList();
Note how the last one works by constructing the projection delegate from a method group, like this:
Func<string, string> projection = Path.GetFileName;
var listToReturn = paths.Select(projection).ToList();
(Just in case that wasn't clear.)
Note that if you don't need to use this as a list - if you just want to iterate over it, in other words - you can drop the ToList() call from each of these approaches.
It's just:
var listToReturn = getPaths().Select(x => Path.GetFileName(x)).ToList();
As already stated in other answers, if you don't actually need a List<string> you can omit the ToList() and simply return IEnumerable<string> (for example if you just need to iterate it, IEnumerable<> is better because avoids the creation of an other list of strings)
Also, given that Select() method takes a delegate, and there's an implicit conversion between method groups and delegates having the same signature, you can skip the lambda and just do:
getPaths().Select(Path.GetFileName)
You could do it like this:
return getPaths().Select(Path.GetFileName);
listToReturn = paths.ToList().Select(p => Path.GetFileName(p));
I was under the impression that the only difference between Func and Action is that the former has to have a return value.So I thought you can call a recursive linq from either a Func or Action. I am new to C# and I am just experimenting and curious.
So I tried the following to recursively print the nested types within a Type.
Type t = typeof(Lev1);
Action<Type> p1 = null, p2 = null;
p1 = tn =>
{
Console.WriteLine(tn.Name);
tn.GetNestedTypes().Select(x => { p1(x); return x; });
};
p2 = tn =>
{
Console.WriteLine(tn.Name);
tn.GetNestedTypes().ToList().ForEach(x => { p2(x);});
};
p1(t);
Console.WriteLine("=".PadRight(50, '='));
p2(t);
So the result I got was that p1 (which uses recursion from a Func-ie Select) only prints the top level whereas p2 which uses Action-ie Foreach prints all levels.
I thought Func is just a function def so recursion is valid. Sure my understanding is wrong can somebody explain
The reason you see only the top-level in the first implementation is because the Select is lazily evaluated. It only starts returning values when it needs to, for example when you iterate it (or when you call Sum or a number of other functions). If you add a ToList() call after the Select, it will work.
You must force the IEnumerable -- it is lazy! (It needn't always be, but be wary with LINQ methods!)
In this case, you discard the results (and the actions!). Oh, well!
You need to add .ToList() to the first Select() call because Linq functions are lazy. In the second call the recursion works because of List<>.ForEach() (which as the name stands does exactly what foreach statement does).