See this sample:
var list = new List<string?>();
foreach (string item in list.Where(i => i != null))
{
if (item.Length == 2)
{
...
}
}
In this sample, I get possible null reference in two places. The foreach variable and the dereferencing of Length in if. The second one I can easily fix by adding a dammit (null-forgiving) operator like this: item!.Length
Is there any way to do the same thing to the first one? I know that I can mark it as nullable string and check again but, I have already checked.
When you apply filtering using Where, you eliminate all null values, but this doesn't change the type of values.
All you need is to cast the results after filtering to the proper type:
foreach (string item in list.Where(i => i != null).Select(x => x!))
Unfortunately the Where predicate doesn't modify the caller's view of whether items in the enumerable are null or not.
The approach given by Dmitry involves additional runtime overhead due to the use of an extra Select call.
You can avoid that overhead via this extension method:
public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> source) where T : class
{
foreach (T? item in source)
{
if (item != null)
yield return item;
}
}
Your code then becomes:
foreach (string item in list.WhereNotNull())
{
if (item.Length == 2)
{
...
}
}
How do I create LINQ to call DoSomething() only once to reduce these duplicate codes? Note that there are some properties in nameValue which I don't need to do anything about it. DoSomething() is only applied for these 4 properties.
foreach (var nameValue in nameDetails.NameValue)
{
if (nameValue.FirstName != null)
{
DoSomething(nameValue.FirstName)
}
if (nameValue.MaidenName != null)
{
DoSomething(nameValue.MaidenName)
}
if (nameValue.MiddleName != null)
{
DoSomething(nameValue.MiddleName)
}
if (nameValue.Surname != null)
{
DoSomething(nameValue.Surname)
}
}
Move the condition into the function and you can write
foreach (var nameValue in nameDetails.NameValue)
{
DoSomethingMaybe(nameValue.FirstName);
DoSomethingMaybe(nameValue.MaidenName);
DoSomethingMaybe(nameValue.MiddleName);
DoSomethingMaybe(nameValue.Surname);
}
void DoSomethingMaybe(string value)
{
if (value != null)
{
DoSomething(value)
}
}
perfectly readable and no unnecessary overhead, no throwaway objects. Maybe not the answer you expect, but LINQ is not magic, that makes things better just be being there.
You may create an array of *names, then use SelectMany to flatten 2 dimensional array into IEnumerable<string> , e.g.:
var enumerable = nameDetails.NameValue.SelectMany(elem => new[]
{
elem.FirstName,
elem.MaidenName,
elem.MiddleName,
elem.Surname
}).Where(value => value != null);
foreach (var value in enumerable)
{
DoSomething(value);
}
My interpretation of your question is that you want to write DoSomething only once but still want to perform it more than once if more than one name part is not null.
You can refactor your code to this:
var names = nameDetails.NameValue
.SelectMany(nv => new string[] { nv.FirstName, nv.MaidenName, nv.MiddleName, nv.Surname })
.Where(name => name != null);
foreach (var name in names)
{
DoSomething(name);
}
This makes use of SelectMany which allows each item of the source enumerable to be mapped into multiple values which are then flattened into an enumerable of the mapped element value's type.
I've created a templated bst class and I've implemented GetEnumerator but I'm really not happy with what've done.
so first of all I felt i needed an helper function inner visit
private IEnumerable<Node<T>> innerVisit(Node<T> root)
{
if(root== null)
yield break;
if (root.Left != null)
{
var l = innerVisit(root.Left);
foreach (var item in l)
yield return item;
}
yield return root;
if (root.Right != null)
{
var r = innerVisit(root.Right);
foreach (var item in r)
yield return item;
}
}
I really dislike the repeating code but couldn't find a proper solution to it
, clearly repeating the loop is unclean but also I feel that burying it under a function that would jump into this one would be bad practice to say the least. any suggestion on how to do this properly?
also to complete the implementation I've written
public IEnumerator<Node<T>> GetEnumerator()
{
var res = innerVisit(_root);
foreach (var item in res)
yield return item;
}
but that too feels bad and more of a hack to make sure it will work within foreach loop and etc.
I don't think you can solve your problem without repeating the same operations like you did, but I do think you can do it in a clearer way, it is part of the requirements to return an IEumerable and If you want to do it in a recursive way you can't prevent reapiting the yield operations (but you don't have to write all of them by yourself, System.LINQ will help us with that).
We can replace the foreach and the yield return with Enumerable.Concat method, using it we can concat the left InnerVisit IEnumerable, IEnumerable that we will create for the node itself (an array with 1 item of the current node) and the right InnerVisit IEnumerable:
private IEnumerable<Node<T>> InnerVisit(Node<T> node)
{
if(node == null)
{
return Enumerable.Empty<Node<T>>;
}
return InnerVisit(node.Left).Concat(new[] { node }).Concat(InnerVisit(node.Right));
}
Notice that there is no need to check if Left or Right is null before you call the recursive method because it will check it later in the inner call, if it is null we will return an Enumerable.Empty<Node<T>> instead of using yield break as you did.
We can also simplify GetEnumerator by calling GetEnumerator directly on the result of the root InnerVisit, something like this:
public IEnumerator<Node<T>> GetEnumerator()
{
return InnerVisit(_root).GetEnumerator();
}
Hello Functional C# Friends,
So this time i am trying to compact my code and write in more functional , lambda style, as well as i would like to avaoid creating unneccessary lists and classes and let compiler do the work for me. I did manage to convert some small piece of code in functional way but after that i dont have much idea as how to go about.
var errorList = new List<DataRow>();
IEnumerable<DataRow> resultRows = GetResultRows();
resultRows
.Filter(row => row.Field<string>("status").Equals("FAILURE", StringComparison.InvariantCultureIgnoreCase))
.ForEach(row => { errorList.Add(row); });
if (errorList.Count > 0)
{
var excludedBooks = new List<string>();
foreach (DataRow row in errorList)
{
if (ToUseBooksList.Contains((string)row["main_book"]))
{
BookCheckResults.AddRow(string.Format("Error for MainBook {0}, RiskType {1}",
row["main_book"], row["risk_type"]));
if (!excludedBooks.Contains((string)row["main_book"]))
{
excludedBooks.Add((string)row["main_book"]);
}
}
}
}
My Extension methods :
public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
{
if (collection == null)
throw new ArgumentNullException("collection");
if (action == null)
throw new ArgumentNullException("action");
foreach (var item in collection)
action(item);
}
public static IEnumerable<T> Filter<T>(this IEnumerable<T> source, Predicate<T> func)
{
foreach (var item in source)
{
if (func(item))
yield return item;
}
}
I will highly appreciate if you can help me structing this code is more functional, lambda style.
Why on earth did you write you own Filter extension method when Where is available?
The ForEach extension method usually isn't worth the bother.
Eric Lippert has blogged about it, and his philosophical objection to it is that it looks like a side-effect free expression (like most Linq features) but it is actually a side-effecting imperative statement in disguise.
If you want to carry out an action for each item on a list, use the foreach statement. That's what it's for.
If you want to manipulate lists of actions, then you can do that, but then you want IEnumerable<Action>.
For the first part of your code, how about:
var errorList = GetResultRows().Where(row => row.Field<string>("status").Equals("FAILURE", StringComparison.InvariantCultureIgnoreCase)
.ToList();
You have a List<string> called excluded books. Use HashSet<string> instead, and you don't need to check if a string is already added to it:
var excludedBooks = new HashSet<string>();
foreach (DataRow row in errorList)
{
if (ToUseBooksList.Contains((string)row["main_book"]))
{
BookCheckResults.AddRow(string.Format("Error for MainBook {0}, RiskType {1}",
row["main_book"], row["risk_type"]));
excludedBooks.Add((string)row["main_book"]);
}
}
You can also filter the list with Where:
var excludedBooks = new HashSet<string>();
foreach (DataRow row in errorList.Where(r => ToUseBooksList.Contains((string)r["main_book"]))
{
BookCheckResults.AddRow(string.Format("Error for MainBook {0}, RiskType {1}",
row["main_book"], row["risk_type"]));
excludedBooks.Add((string)row["main_book"]);
}
What's the "best" (taking both speed and readability into account) way to determine if a list is empty? Even if the list is of type IEnumerable<T> and doesn't have a Count property.
Right now I'm tossing up between this:
if (myList.Count() == 0) { ... }
and this:
if (!myList.Any()) { ... }
My guess is that the second option is faster, since it'll come back with a result as soon as it sees the first item, whereas the second option (for an IEnumerable) will need to visit every item to return the count.
That being said, does the second option look as readable to you? Which would you prefer? Or can you think of a better way to test for an empty list?
Edit #lassevk's response seems to be the most logical, coupled with a bit of runtime checking to use a cached count if possible, like this:
public static bool IsEmpty<T>(this IEnumerable<T> list)
{
if (list is ICollection<T>) return ((ICollection<T>)list).Count == 0;
return !list.Any();
}
You could do this:
public static Boolean IsEmpty<T>(this IEnumerable<T> source)
{
if (source == null)
return true; // or throw an exception
return !source.Any();
}
Edit: Note that simply using the .Count method will be fast if the underlying source actually has a fast Count property. A valid optimization above would be to detect a few base types and simply use the .Count property of those, instead of the .Any() approach, but then fall back to .Any() if no guarantee can be made.
I would make one small addition to the code you seem to have settled on: check also for ICollection, as this is implemented even by some non-obsolete generic classes as well (i.e., Queue<T> and Stack<T>). I would also use as instead of is as it's more idiomatic and has been shown to be faster.
public static bool IsEmpty<T>(this IEnumerable<T> list)
{
if (list == null)
{
throw new ArgumentNullException("list");
}
var genericCollection = list as ICollection<T>;
if (genericCollection != null)
{
return genericCollection.Count == 0;
}
var nonGenericCollection = list as ICollection;
if (nonGenericCollection != null)
{
return nonGenericCollection.Count == 0;
}
return !list.Any();
}
LINQ itself must be doing some serious optimization around the Count() method somehow.
Does this surprise you? I imagine that for IList implementations, Count simply reads the number of elements directly while Any has to query the IEnumerable.GetEnumerator method, create an instance and call MoveNext at least once.
/EDIT #Matt:
I can only assume that the Count() extension method for IEnumerable is doing something like this:
Yes, of course it does. This is what I meant. Actually, it uses ICollection instead of IList but the result is the same.
I just wrote up a quick test, try this:
IEnumerable<Object> myList = new List<Object>();
Stopwatch watch = new Stopwatch();
int x;
watch.Start();
for (var i = 0; i <= 1000000; i++)
{
if (myList.Count() == 0) x = i;
}
watch.Stop();
Stopwatch watch2 = new Stopwatch();
watch2.Start();
for (var i = 0; i <= 1000000; i++)
{
if (!myList.Any()) x = i;
}
watch2.Stop();
Console.WriteLine("myList.Count() = " + watch.ElapsedMilliseconds.ToString());
Console.WriteLine("myList.Any() = " + watch2.ElapsedMilliseconds.ToString());
Console.ReadLine();
The second is almost three times slower :)
Trying the stopwatch test again with a Stack or array or other scenarios it really depends on the type of list it seems - because they prove Count to be slower.
So I guess it depends on the type of list you're using!
(Just to point out, I put 2000+ objects in the List and count was still faster, opposite with other types)
List.Count is O(1) according to Microsoft's documentation:
http://msdn.microsoft.com/en-us/library/27b47ht3.aspx
so just use List.Count == 0 it's much faster than a query
This is because it has a data member called Count which is updated any time something is added or removed from the list, so when you call List.Count it doesn't have to iterate through every element to get it, it just returns the data member.
The second option is much quicker if you have multiple items.
Any() returns as soon as 1 item is found.
Count() has to keep going through the entire list.
For instance suppose the enumeration had 1000 items.
Any() would check the first one, then return true.
Count() would return 1000 after traversing the entire enumeration.
This is potentially worse if you use one of the predicate overrides - Count() still has to check every single item, even it there is only one match.
You get used to using the Any one - it does make sense and is readable.
One caveat - if you have a List, rather than just an IEnumerable then use that list's Count property.
#Konrad what surprises me is that in my tests, I'm passing the list into a method that accepts IEnumerable<T>, so the runtime can't optimize it by calling the Count() extension method for IList<T>.
I can only assume that the Count() extension method for IEnumerable is doing something like this:
public static int Count<T>(this IEnumerable<T> list)
{
if (list is IList<T>) return ((IList<T>)list).Count;
int i = 0;
foreach (var t in list) i++;
return i;
}
... in other words, a bit of runtime optimization for the special case of IList<T>.
/EDIT #Konrad +1 mate - you're right about it more likely being on ICollection<T>.
Ok, so what about this one?
public static bool IsEmpty<T>(this IEnumerable<T> enumerable)
{
return !enumerable.GetEnumerator().MoveNext();
}
EDIT: I've just realized that someone has sketched this solution already. It was mentioned that the Any() method will do this, but why not do it yourself? Regards
Another idea:
if(enumerable.FirstOrDefault() != null)
However I like the Any() approach more.
This was critical to get this to work with Entity Framework:
var genericCollection = list as ICollection<T>;
if (genericCollection != null)
{
//your code
}
If I check with Count() Linq executes a "SELECT COUNT(*).." in the database, but I need to check if the results contains data, I resolved to introducing FirstOrDefault() instead of Count();
Before
var cfop = from tabelaCFOPs in ERPDAOManager.GetTable<TabelaCFOPs>()
if (cfop.Count() > 0)
{
var itemCfop = cfop.First();
//....
}
After
var cfop = from tabelaCFOPs in ERPDAOManager.GetTable<TabelaCFOPs>()
var itemCfop = cfop.FirstOrDefault();
if (itemCfop != null)
{
//....
}
private bool NullTest<T>(T[] list, string attribute)
{
bool status = false;
if (list != null)
{
int flag = 0;
var property = GetProperty(list.FirstOrDefault(), attribute);
foreach (T obj in list)
{
if (property.GetValue(obj, null) == null)
flag++;
}
status = flag == 0 ? true : false;
}
return status;
}
public PropertyInfo GetProperty<T>(T obj, string str)
{
Expression<Func<T, string, PropertyInfo>> GetProperty = (TypeObj, Column) => TypeObj.GetType().GetProperty(TypeObj
.GetType().GetProperties().ToList()
.Find(property => property.Name
.ToLower() == Column
.ToLower()).Name.ToString());
return GetProperty.Compile()(obj, str);
}
Here's my implementation of Dan Tao's answer, allowing for a predicate:
public static bool IsEmpty<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
if (source == null) throw new ArgumentNullException();
if (IsCollectionAndEmpty(source)) return true;
return !source.Any(predicate);
}
public static bool IsEmpty<TSource>(this IEnumerable<TSource> source)
{
if (source == null) throw new ArgumentNullException();
if (IsCollectionAndEmpty(source)) return true;
return !source.Any();
}
private static bool IsCollectionAndEmpty<TSource>(IEnumerable<TSource> source)
{
var genericCollection = source as ICollection<TSource>;
if (genericCollection != null) return genericCollection.Count == 0;
var nonGenericCollection = source as ICollection;
if (nonGenericCollection != null) return nonGenericCollection.Count == 0;
return false;
}
List<T> li = new List<T>();
(li.First().DefaultValue.HasValue) ? string.Format("{0:yyyy/MM/dd}", sender.First().DefaultValue.Value) : string.Empty;
myList.ToList().Count == 0. That's all
This extension method works for me:
public static bool IsEmpty<T>(this IEnumerable<T> enumerable)
{
try
{
enumerable.First();
return false;
}
catch (InvalidOperationException)
{
return true;
}
}