In C#, if I have a CollectionBase of type T, and each item in the CollectionBase can have a child CollectionBase of the same type T, how can I get a list of all type T objects without using a recursive function?
Does LINQ have a feature to do this?
Thanks in advance.
Wes Dyer wrote actually a nice topic on this, have a look.
As for your case I think you would need an iterator, probably something like this:
public static IEnumerable<T> Flatten<T>(this IEnumerable<T> e, Func<T,IEnumerable<T>> f)
{
return e.SelectMany(c => f(c).Flatten(f)).Concat(e);
}
This is answer is taken from here.
EDIT: I just remember that you can also traverse the tree.
public static IEnumerable<T> Traverse<T>(T item, Func<T, IEnumerable<T>> childSelector)
{
var stack = new Stack<T>();
stack.Push(item);
while (stack.Any())
{
var next = stack.Pop();
yield return next;
foreach (var child in childSelector(next))
stack.Push(child);
}
}
Related
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
foreach (var element in source) action(element);
return source;
}
The code above gives me a warning that source is potentially iterated multiple times, but is it really? It's iterated once in the foreach statement, but how does the return statement make it iterated again?
The return doesn't iterate the enumerable again. But you are returning it, and since the only way you could possibly do ANYTHING with this result is to iterate it elsewhere, this warning is given.
Why return it if you are not going to iterate it later?
In the current code you show there is only one iteration. It is very well possible that you are enumerating it again somewhere else since the same enumerable is returned. That is what the warning is telling you.
My personal preference would be to change the return type of the ForEach to void, and add a second one that returns the result of a Func<T, R>.
So:
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
foreach (var element in source)
action(element);
}
And:
public static IEnumerable<R> ForEach<T, R>(this IEnumerable<T> source, Func<T, R> action)
{
foreach (var element in source)
yield return action(element);
}
That way you are never accidentally reusing the same enumerable and you are making it lazy: it won't execute before you actually call the enumerable.
So I'm coming from Java and is a bit confused on how to use Generics with C#. I have lambda function that should take a list and predicate (of varying object types). When I specify that I want to use generic, the compiler complains that it cannot find T. This is my lambda:
private List<T> LoopCompareLambda(List<T> list, Predicate<T> condition)
{
List<T> returnList = new List<T>();
foreach (T sensor in list)
{
if (condition(sensor))
{
returnList.Add(sensor);
}
}
return returnList;
}
Try
private List<T> LoopCompareLambda<T>(List<T> list, Predicate<T> condition)
The <T> must be after the method name and before the (.
Note that the signature could be (with the code you wrote):
private static List<T> LoopCompareLambda<T>(IEnumerable<T> list, Predicate<T> condition)
And in .NET there is a strong preference for using Func<T, bool> instead of Predicate<T>
private static List<T> LoopCompareLambda<T>(IEnumerable<T> list, Func<T, bool> condition)
Change the signiture of your method to
private List<T> LoopCompareLambda<T>(List<T> list, Predicate<T> condition)
You have to add your generic type to the method. You can use multiple generics in one method and add conditions like
private List<T> LoopCompareLambda<T>(List<T> list, Predicate<T> condition) where T : class, new()
as well.
Your class needs to be generic.
class MyGenericClass<T>
{
...
}
Given an existing ICollection<T> instance (e.g. dest) what is the most efficient and readable way to add items from an IEnumerable<T>?
In my use case, I have some kind of utility method Collect(IEnumerable items) which returns a new ICollection with the elements from items, so I am doing it in the following way:
public static ICollection<T> Collect<T>(IEnumerable<T> items) where T:ICollection<T>
{
...
ICollection<T> dest = Activator.CreateInstance<T>();
items.Aggregate(dest, (acc, item) => { acc.Add(item); return acc; });
...
return dest;
}
Question: Is there any “better” way (more efficient or readable) of doing it?
UPDATE: I think the use of Aggregate() is quite fluent and not so inefficient as invoking ToList().ForEach(). But it does not look very readable. Since nobody else agrees with the use of Aggregate() I would like to read your reasons to NOT use Aggregate() for this purpose.
Just use Enumerable.Concat:
IEnumerable<YourType> result = dest.Concat(items);
If you want a List<T> as result use ToList:
List<YourType> result = dest.Concat(items).ToList();
// perhaps:
dest = result;
If dest is actually already a list and you want to modify it use AddRange:
dest.AddRange(items);
Update:
if you have to add items to a ICollection<T> method argument you could use this extension:
public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> seq)
{
List<T> list = collection as List<T>;
if (list != null)
list.AddRange(seq);
else
{
foreach (T item in seq)
collection.Add(item);
}
}
// ...
public static void Foo<T>(ICollection<T> dest)
{
IEnumerable<T> items = ...
dest.AddRange(items);
}
Personally I'd go with #ckruczek's comment of a foreach loop:
foreach (var item in items)
dest.Add(item);
Simple, clean, and pretty much everybody immediately understands what it does.
If you do insist on some method call hiding the loop, then some people define a custom ForEach extension method for IEnumerable<T>, similar to what's defined for List<T>. The implementation is trivial:
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) {
if (source == null) throw new ArgumentNullException(nameof(source));
if (action == null) throw new ArgumentNullException(nameof(action));
foreach (item in source)
action(item);
}
Given that, you would be able to write
items.ForEach(dest.Add);
I don't see much benefit in it myself, but no drawbacks either.
We actually wrote an extension method for this (along with a bunch of other ICollection extension methods):
public static class CollectionExt
{
public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> source)
{
Contract.Requires(collection != null);
Contract.Requires(source != null);
foreach (T item in source)
{
collection.Add(item);
}
}
}
So we can just use AddRange() on an ICollection():
ICollection<int> test = new List<int>();
test.AddRange(new [] {1, 2, 3});
Note: If you wanted to use List<T>.AddRange() if the underlying collection was of type List<T> you could implement the extension method like so:
public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> source)
{
var asList = collection as List<T>;
if (asList != null)
{
asList.AddRange(source);
}
else
{
foreach (T item in source)
{
collection.Add(item);
}
}
}
Most efficient:
foreach(T item in itens) dest.Add(item)
Most readable (BUT inefficient because it is creating a throwaway list):
items.ToList().ForEach(dest.Add);
Less readable, but Not so inefficient:
items.Aggregate(dest, (acc, item) => { acc.Add(item); return acc; });
items.ToList().ForEach(dest.Add);
If you dont want to create a new collection instance, then create an extension method.
public static class Extension
{
public static void AddRange<T>(this ICollection<T> source, IEnumerable<T> items)
{
if (items == null)
{
return;
}
foreach (T item in items)
{
source.Add(item);
}
}
}
Then you can edit your code like this:
ICollection<T> dest = ...;
IEnumerable<T> items = ...;
dest.AddRange(items);
What is Linq actually doing?
(I'm assuming this is for LINQ to Objects. Anything else will be implemented differently :)
It's just returning everything from the first, and then everything from the second. All data is streamed. Something like this:
public static IEnumerable<T> Concat(this IEnumerable<T> source1,
IEnumerable<T> source2)
{
if (source1 == null)
{
throw new ArgumentNullException("source1");
}
if (source2 == null)
{
throw new ArgumentNullException("source1");
}
return ConcatImpl(source1, source2);
}
private static IEnumerable<T> ConcatImpl(this IEnumerable<T> source1,
IEnumerable<T> source2)
{
foreach (T item in source1)
{
yield return item;
}
foreach (T item in source2)
{
yield return item;
}
}
I've split this into two methods so that the argument validation can be performed eagerly but I can still use an iterator block. (No code within an iterator block is executed until the first call to MoveNext() on the result.)
It enumerates each collection in turn, and yields each element. Something like that :
public static IEnumerable<T> Concat<T>(this IEnumerable<T> source, IEnumerable<T> other)
{
foreach(var item in source) yield return item;
foreach(var item in other) yield return item;
}
(if you look at the actual implementation using Reflector, you will see that the iterator is actually implemented in a separate method)
It depends on the LINQ provider you are using. LinqToSql or L2E might use a database UNION, whereas LINQ to Objects might just enumerate both collections for your in turn.
I need to be able to access a property via reflection, and, knowing that this property is an IEnumerable, append an object to it.
Something like this:
Object o;
MemberInfo m;
Array arr; // Except use IEnumerable, may have to take account of value/ref types
arr = (Array)((PropertyInfo)m).GetValue(o, null); }
List<o.GetType()> newArr = new List<o.GetType()>(); /* fails */
newArr.AddRange(arr);
newArr.Add(o);
((PropertyInfo)m).SetValue(o, newArr.ToArray(), null);
Can you help me where I'm going wrong :-)
Solution:
See accepted answer comments. Also (Get the actual type of a generic object parameter) is of help.
Once you have an IEnumerable type, use something like this to append to it:
public static IEnumerable<T> Append<T>(this IEnumerable<T> original, T next)
{
foreach (T item in original) yield return item;
yield return next;
}
public static IEnumerable<T> Append<T>(this IEnumerable<T> original, params T[] next)
{
foreach (T item in original) yield return item;
foreach (T item in next) yield return item;
}
public static IEnumerable<T> Append<T>(this IEnumerable<T> original, IEnumerable<T> next)
{
foreach (T item in original) yield return item;
foreach (T item in next) yield return item;
}
It sounds like you're essentially asking how to make a List<T> based on an unknown-at-compile-time type. For this you'll have to use a bit more reflection magic:
Type genericListType = typeof(List<>);
Type listType = genericListType.MakeGenericType(o.GetType());
object listInstance = Activator.CreateInstance(listType);
That would create a List<T> out of a runtime type.
But really, your code would be much simpler if you simply use ArrayList:
ArrayList list = new ArrayList(arr);
list.Add(o);
Array newArray = list.ToArray(o.GetType());