I have encountered in my code similiar situation to the one presented in code below. The problem is that for some reason iterating in foreach loop throws NullReferenceException.
My question is, why this happens?
If I create iterator that returns empty element myself, foreach handles it, and simply prints empty line.
Result of following code is: test, test, NullReferenceException.
using System;
using System.Collections.Generic;
using System.Linq;
public class NestedB
{
public string Test {get;set;}
}
public class NestedA
{
public List<NestedB> NestedCollection {get;set;}
}
public class Program
{
public static void Main()
{
var listOfA = new List<NestedA>
{
new NestedA
{
NestedCollection = new List<NestedB>
{
new NestedB {Test = "test"},
new NestedB {Test = "test"}
}
},
new NestedA ()
};
var listOfB = listOfA.SelectMany(x => x.NestedCollection);
foreach (var item in listOfB)
{
if (item != null)
{
Console.WriteLine(item.Test);
}
}
}
}
Stacktrace:
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
at System.Linq.Enumerable.SelectManySingleSelectorIterator`2.MoveNext()
at Program.Main()
Command terminated by signal 6
This is the problem:
listOfA.SelectMany(x => x.NestedCollection)
Your second NestedA instance doesn't have a NestedCollection, so it's trying to find "all the items in a null reference". You'd have exactly the same problem if you did this manually:
var nestedA = new NestedA();
// This will throw an exception, because nestedA.NestedCollectoin is null
foreach (var nestedB in nestedA.NestedCollection)
{
}
The simplest fix to this would be to make NestedCollection a read-only property, but initialize it to start with:
public List<NestedB> NestedCollection { get; } = new List<NestedB>();
Then you'll need to modify the initialization of your first NestedA to use a collection initializer:
new NestedA
{
NestedCollection =
{
new NestedB { Test = "test" },
new NestedB { Test = "test" }
}
}
If you don't want to do that, you could change the SelectMany call instead:
var listOfB = listOfA.SelectMany(x => x.NestedCollection ?? Enumerable.Empty<NestedB>())
The implementation of SelectMany is something like this:
public static IEnumerable<TResult> SelectMany<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, IEnumerable<TResult>> selector)
{
if (source == null)
throw Error.ArgumentNull(nameof (source));
if (selector == null)
throw Error.ArgumentNull(nameof (selector));
return Enumerable.SelectManyIterator<TSource, TResult>(source, selector);
}
private static IEnumerable<TResult> SelectManyIterator<TSource, TResult>(
IEnumerable<TSource> source,
Func<TSource, IEnumerable<TResult>> selector)
{
foreach (TSource source1 in source)
{
foreach (TResult result in selector(source1)) // The error throws here
yield return result;
}
}
Note the comment line. The selector(source1) will return a null for the second NestedA item and this line will try to get the enumerator of the null item(foreach). That's why you got the error.
To complement the existing answers:
Compilation optimization and runtime optimization can cause inaccuracies in the reported line numbers. It is useful to examine not just the enumerable, but also the foreach body for possible dereferenced nulls, especially if iterating over a (statically declared) array.
Related
I have a method that expect IEnumerable<string> as you can see here :
public static string FromDecimalAscii(IEnumerable<string> input)
{
return new string(input.Select(s => (char)int.Parse(s)).ToArray());
}
But every time the last record of my IEnumerable is empty so i got an error in this line because of that :
return new string(input.Select(s => (char)int.Parse(s)).ToArray());
So i have to remove that item from my IEnumerable .
The error:Input string was not in a correct format
Any ideas will be appreciated.
Best regards
You need just to filter collection with Where:
return new string(input.Where(s => !string.IsNullOrEmpty(s))
.Select(s => (char)int.Parse(s)).ToArray());
You can also use extension method to use TryParse:
static class Extensions
{
public delegate bool TryParseDelegate<TSource>(string s, out TSource source);
public static IEnumerable<TResult> WhereParsed<TSource, TResult>(
this IEnumerable<TSource> source,
TryParseDelegate<TResult> tryParse)
{
// TODO: check arguments against null first
foreach (var item in source)
{
TResult result;
if (tryParse(item != null ? item.ToString() : null, out result))
{
yield return result;
}
}
}
}
Usage:
var collection = input.WhereParsed<string, int>(int.TryParse)
.Cast<char>()
.ToArray();
return new string(collection);
Assuming the ienumerable is not null, a foreach loop simply won't execute if that ienumerable is empty. But instead, I need to run other code if the collection is empty. Here's sample code which works flawlessly:
List<string> theList = new List<string>() {};
if (theList.Count > 0) {
foreach (var item in theList) {
//do stuff
}
} else {
//throw exception or do whatever else
}
Is there anyway to shorten this up via out-of-the-box C#, an Extension Method, etc? In my head I was thinking the following would be cool, but obviously it doesn't work:
List<string> theList = new List<string>() {};
foreach (var item in theList) {
//do stuff
} else {
//throw exception or do whatever else
}
EDIT: My solution thanks to insight from Maarten: The following will throw an exception if the collection is null or empty (if you want to simply ignore cases where the collection is null or empty, use a ternary operator in the foreach)
static class Extension {
public static IEnumerable<T> FailIfNullOrEmpty<T>(this IEnumerable<T> collection) {
if (collection == null || !collection.Any())
throw new Exception("Collection is null or empty");
return collection;
}
}
class Program {
List<string> theList = new List<string>() { "a" };
foreach (var item in theList.FailIfNullOrEmpty()) {
//do stuff
}
}
If you really wanted to achieve this, you could create an extension method (like you said yourself).
class Program {
static void Main(string[] args) {
List<string> data = new List<string>();
foreach (var item in data.FailIfEmpty(new Exception("List is empty"))) {
// do stuff
}
}
}
public static class Extensions {
public static IEnumerable<T> FailIfEmpty<T>(this IEnumerable<T> collection, Exception exception) {
if (!collection.Any()) {
throw exception;
}
return collection;
}
}
You can throw the exception beforehand, without having to write the else block:
if(mylist.Count == 0)
throw new Exception("Test");
foreach(var currItem in mylist)
currItem.DoStuff();
The execution flow won't reach the loop if the exception has been raised.
I have a problem with a List of objects ...
This List contains objects which themselves contain objects, and so on ... (all objects are of the same type)
My objects looks like that :
public class MyObject (...)
{
...
public MyObject[] Object;
...
}
I'd like to change some variables of these objects (according to certain parameters), and to do that I think using LINQ.
My problem is that I do not really know how to do something that will pass through ALL my recursive List, regardless of their level.
I hope I was as clear as possible.
Thank you in advance for your help.
You can write a simple recursive method to do what you want easily enough:
public static void Touch(MyObject obj, string otherParameter)
{
obj.Value = otherParameter;
foreach (var child in obj.Object)
{
Touch(child, otherParameter);
}
}
If you really, really want a more LINQ-esque method, or you do this often enough to need a more generic approach, you could use something like this:
public static IEnumerable<T> FlattenTree<T>(IEnumerable<T> source, Func<T, IEnumerable<T>> selector)
{
//you could change this to a Queue or any other data structure
//to change the type of traversal from depth first to breath first or whatever
var stack = new Stack<T>();
while (stack.Any())
{
T next = stack.Pop();
yield return next;
foreach (T child in selector(next))
stack.Push(child);
}
}
You could then use it like:
MyObject root = new MyObject();
var allNodes = FlattenTree(new[] { root }, node => node.Object);
foreach (var node in allNodes)
{
node.Value = "value";
}
You could use this recursive extension method:
public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> fnRecurse)
{
foreach (T item in source)
{
yield return item;
IEnumerable<T> seqRecurse = fnRecurse(item);
if (seqRecurse != null)
{
foreach (T itemRecurse in Traverse(seqRecurse, fnRecurse))
{
yield return itemRecurse;
}
}
}
}
You can use it in this way:
var allObj = list.Traverse(o => o.Object);
foreach (MyObject o in allObj)
{
// do something
}
It's handy because it's generic and works with any type and also because it's using deferred execution.
Maybe simply something like this:
static void AddRecursively(MyObject obj, List<MyObject> listToAddTo)
{
listToAddTo.Add(obj);
foreach (var o in obj.Object)
AddRecursively(o, listToAddTo);
}
I suggest to use this extension method that applies an action to all the items recursively
public static void ForEach<T>(this IEnumerable<T> source,
Func<T, IEnumerable<T>> getChildren,
Action<T> action)
{
if (source == null) {
return;
}
foreach (T item in source) {
action(item);
IEnumerable<T> children = getChildren(item);
children.ForEach(getChildren, action);
}
}
You would apply it to your list like this
myObjectList.ForEach(x => x.Object, x => x.Value = "new value");
The first paramter tells ForEach how to access the nested objects. The second parameter tells what to do with each item.
I'd like a general solution but as an example, assume i have an IEnumerable<string>, where some can be parsed as integers, and some cannot.
var strings = new string[] { "1", "2", "notint", "3" };
Obviously if i did Select(s => int.Parse(s, temp)) it'd throw an exception when enumerated.
In this case i could do .All(s => int.TryParse(s, out temp)) first, however i want a general solution where i don't have to enumerate the IEnumerable twice.
Ideally i'd like to be able to do the following, which calls my magic exception skipping method:
// e.g. parsing strings
var strings = new string[] { "1", "2", "notint", "3" };
var numbers = strings.Select(s => int.Parse(s)).SkipExceptions();
// e.g. encountering null object
var objects = new object[] { new object(), new object(), null, new object() }
var objecttostrings = objects.Select(o => o.ToString()).SkipExceptions();
// e.g. calling a method that could throw
var myClassInstances = new MyClass[] { new MyClass(), new MyClass(CauseMethodToThrow:true) };
var myClassResultOfMethod = myClassInstances.Select(mci => mci.MethodThatCouldThrow()).SkipExceptions();
How can i write the SkipExceptions() extension method?
Some great answers for a SelectSkipExceptions() method, however i wonder if a SkipExceptions() method could be created, along the same lines as AsParallel().
How about this (you might want to give this special Select Extension a better name)
public static IEnumerable<TOutput> SelectIgnoringExceptions<TInput, TOutput>(
this IEnumerable<TInput> values, Func<TInput, TOutput> selector)
{
foreach (var item in values)
{
TOutput output = default(TOutput);
try
{
output = selector(item);
}
catch
{
continue;
}
yield return output;
}
}
Edit5
Added a using statement, thanks for the suggestion in comments
public static IEnumerable<T> SkipExceptions<T>(
this IEnumerable<T> values)
{
using(var enumerator = values.GetEnumerator())
{
bool next = true;
while (next)
{
try
{
next = enumerator.MoveNext();
}
catch
{
continue;
}
if(next) yield return enumerator.Current;
}
}
}
However this relies on the incoming IEnumerable not already being created (and therefore already having thrown Exceptions) as a list by the preceding Function. E.g. this would probably not work if you call it like this: Select(..).ToList().SkipExceptions()
Create a TryParseInt method that returns a Nullable<int>:
int? TryParseInt(string s)
{
int i;
if (int.TryParse(s, out i))
return i;
return null;
}
And use it in your query like that:
var numbers = strings.Select(s => TryParseInt(s))
.Where(i => i.HasValue)
.Select(i => i.Value);
See also this article by Bill Wagner, which presents a very similar case.
Now, i don't think you can write something like a generic SkipExceptions method, because you would catch the exception too late, and it would end the Select loop... But you could probably write a SelectSkipException method:
public static IEnumerable<TResult> SelectSkipExceptions<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> selector)
{
if (source == null)
throw new ArgumentNullException("source");
if (selector == null)
throw new ArgumentNullException("selector");
return source.SelectSkipExceptionsIterator(selector);
}
private static IEnumerable<TResult> SelectSkipExceptionsIterator<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> selector)
{
foreach(var item in source)
{
TResult value = default(TResult);
try
{
value = selector(item);
}
catch
{
continue;
}
yield return value;
}
}
Even the accepted answer may not be "general" enough. What if some day you find that you need to know what exceptions occurred?
The following extension
static class EnumeratorHelper {
//Don't forget that GetEnumerator() call can throw exceptions as well.
//Since it is not easy to wrap this within a using + try catch block with yield,
//I have to create a helper function for the using block.
private static IEnumerable<T> RunEnumerator<T>(Func<IEnumerator<T>> generator,
Func<Exception, bool> onException)
{
using (var enumerator = generator())
{
if (enumerator == null)
yield break;
for (; ; )
{
//You don't know how to create a value of T,
//and you don't know weather it can be null,
//but you can always have a T[] with null value.
T[] value = null;
try
{
if (enumerator.MoveNext())
value = new T[] { enumerator.Current };
}
catch (Exception e)
{
if (onException(e))
continue;
}
if (value != null)
yield return value[0];
else
yield break;
}
}
}
public static IEnumerable<T> WithExceptionHandler<T>(this IEnumerable<T> orig,
Func<Exception, bool> onException)
{
return RunEnumerator(() =>
{
try
{
return orig.GetEnumerator();
}
catch (Exception e)
{
onException(e);
return null;
}
}, onException);
}
}
will help. Now you can add SkipExceptions:
public static IEnumerable<T> SkipExceptions<T>(this IEnumerable<T> orig){
return orig.WithExceptionHandler(orig, e => true);
}
By using different onException callback, you can do different things
Break the iteration but ignore the exception: e => false
Try to continue iteration: e => true
Log the exception, etc
Here's a small complete program to demonstrate an answer inspired by the maybe monad. You might want to change the name of the 'Maybe' class, as it is inspired by rather than actually being a 'Maybe' as defined in other languages.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestMaybe
{
class Program
{
static void Main(string[] args)
{
var strings = new string[] { "1", "2", "notint", "3" };
var ints = strings.Select(s => new Maybe<string, int>(s, str => int.Parse(str))).Where(m => !m.nothing).Select(m => m.value);
foreach (var i in ints)
{
Console.WriteLine(i);
}
Console.ReadLine();
}
}
public class Maybe<T1, T2>
{
public readonly bool nothing;
public readonly T2 value;
public Maybe(T1 input, Func<T1, T2> map)
{
try
{
value = map(input);
}
catch (Exception)
{
nothing = true;
}
}
}
}
Edit: depending on the needs of your code, you might also want nothing set to true if the result of map(input) is null.
This is the same answer as Thomas's, but with a lambda & LINQ expression. +1 for Thomas.
Func<string, int?> tryParse = s =>
{
int? r = null;
int i;
if (int.TryParse(s, out i))
{
r = i;
}
return r;
};
var ints =
from s in strings
let i = tryParse(s)
where i != null
select i.Value;
You could just chain the Where and Select method together.
var numbers = strings.Where(s =>
{
int i;
return int.TryParse(s, out i);
}).Select(int.Parse);
The use of the Where method effectively removes the need for you to write your own SkipExceptions method, because this is basically what you are doing.
I just want to know if there is a foreach oneliner in C#, like the if oneliner (exp) ? then : else.
If you're dealing with an array then you can use the built-in static ForEach method:
Array.ForEach(yourArray, x => Console.WriteLine(x));
If you're dealing with a List<T> then you can use the built-in ForEach instance method:
yourList.ForEach(x => Console.WriteLine(x));
There's nothing built-in that'll work against any arbitrary IEnumerable<T> sequence, but it's easy enough to roll your own extension method if you feel that you need it:
yourSequence.ForEach(x => Console.WriteLine(x));
// ...
public static class EnumerableExtensions
{
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
if (source == null) throw new ArgumentNullException("source");
if (action == null) throw new ArgumentNullException("action");
foreach (T item in source)
{
action(item);
}
}
}
List.ForEach Method
Imagine you have three variables and you want to set the same property of them all in only one go:
foreach (var item in new [] {labelA, labelB, labelC})
{
item.Property= Value;
}
It is the equivalent of doing:
foreach (var item in new List<SomeType>(){labelA, labelB, labelC})
{
item.Property= Value;
}
foreach line-liners could be achieved with LINQ extension methods. For example:
instead of:
var result = new List<string>();
foreach (var item in someCollection)
{
result.Add(item.Title);
}
you could:
var result = someCollection.Select(x => x.Title).ToList();
Sure, you can use something like List<>.ForEach:
List<String> s = new List<string>();
s.Add("This");
s.Add("Is");
s.Add("Some");
s.Add("Data");
s.ForEach(_string => Console.WriteLine(_string));
The primary difference between if and the ?operator is that if is a statement, while ? produces an expression. I.e. you can do this:
var _ = (exp) ? then : else; // ok
but not this:
var _ = if (exp) { then; } else { else; }; // error
So if you are looking for something like a foreach expression, there is no .NET type that can naturally return except for void, but there are no values of void type, so you can equally just write:
foreach (var item in collection) process(item);
In many functional languages, a Unit type is used instead of void which is a type with only one value. You can emulate this in .NET and create your own foreach expression:
class Unit
{
public override bool Equals(object obj)
{
return true;
}
public override int GetHashCode()
{
return 0;
}
}
public static class EnumerableEx
{
public static Unit ForEach<TSource>(
this IEnumerable<TSource> source,
Action<TSource> action)
{
foreach (var item in source)
{
action(item);
}
return new Unit();
}
}
However there hardly exists any use-case for such expressions.