I'd like to use a for each loop to iterate over two Collections. My first idea was:
foreach (object o in a.Concat(b)) {
o.DoSomething(); }
But the problem is, not all Collections support Concat. So what do to?
Some legacy collection types implement only IEnumerable and not IEnumerable<T>, and therefore don't have the Concat extension method. You can solve this by first using the method Enumerable.Cast<T> and specifying the generic type you want, then it will work with Concat.
Instead of ...
foreach (object o in a.Concat(b)) {
o.DoSomething(); }
Why not just ?
foreach (object o in a) {
o.DoSomething();
}
foreach (object o in b) {
o.DoSomething();
}
If you really want them to be both in the same list, construct a new list and add them together before you start processing.
Related
so far I have done this:
List<string[]> VList
foreach (var item in VList)
{
foreach (var b in item)
{
Richtextbox 1 = VList[item][b]?
}
}
How do I do this correct? I want it to write everything that the list contains
A foreach loop iterates a collection1 using an IEnumerator1.
In each iteration, the loop variable (item and b in your case) references whatever the IEnumerator.Current property is referencing.
The square brackets [] are used for a special kind of property called indexers. Indexers are typically used in a collection2 to provide a reference to whatever the collection is holding that is coupled to that specific index.
When you are using a foreach loop, you don't need to know the index of an element in the collection - and in fact, the collection doesn't even have to support indexes - you already have a reference to it via the loop variable.
So a code that uses a nested foreach loop to do something with the strings inside a variable of type List<string[]> would be something like this:
foreach(var stringArray in VList)
{
foreach(var str in stringArray)
{
// do something with str here...
}
}
If you want to use indexers, use a for loop instead:
for(var i=0; i<VList.Count; i++)
{
for(var j=0; j<VList[i].Length; j++)
{
// do something with VList[i][j] here...
}
}
1 Actually, a foreach loop doesn't need an actual collection to work with.
It only needs an instance that has a method called GetEnumerator() that returns an object that has a public property called Current and a public method called MoveNext.
This means that even if you have a class that doesn't implement the IEnumerable interface but has the GetEumerator method, and that method returns an instance of some other class that doesn't implement the IEnumerable interface but has the Current property and the MoveNext method, you can still use foreach with that. This is called duck typing.
This is documented in foreach, in (C# reference)
2 The fact that a type has indexer doesn't have to mean that the type is a collection - it's perfectly valid to add indexres to your own type without implementing any interface collections usually implement such as IEnumerable or ICollection.
Your access is wrong. You are iterating over the elements there is no need to use the array/indexer access. []
List<string[]> VList
foreach (var item in VList)
{
foreach (var b in item)
{
Richtextbox1.text += b
}
}
I have Dictionary<T, T> that contains a key (that represents a category) with an empty List<T> as value:
Dictionary<string, List<IMyObject>> myObjects;
Each pair looks something like this:
{ firstCategory, new List<IMyObject>> }
I now have a List<T> of IMyObject's:
List<IMyObject> myObjectsUnsorted;
I want to loop through myObjectsUnsorted and add to the correct List<T>
foreach (var myObject in myObjectsUnsorted)
{
myObjects[myObject.Category].Add(myObject);
}
How can I do this without a loop? For example with a LINQ extension method? My other objects in this example is created with .Select() but that dosen't really fit the bill in this last foreach.
I would suggest using a lookup instead:
ILookup<string, IMyObject> lookup = myObjectsUnsorted.ToLookup(t => t.Category);
ILookup<,> is precisely designed to be a "multiple values per key" dictionary. As well as being incredibly simple to construct, it has the benefit that if you look up a key which isn't represented, you get an empty sequence back instead of an exception. So you can always just write:
foreach (var item in lookup[key])
{
...
}
As opposed to:
IList<MyObject> list;
if (dictionary.TryGetValue(key, out list))
{
foreach (var item in list)
{
...
}
}
Note that a lookup is immutable in that you can't change which items are in it after construction. (If the items are mutable reference types, you can modify the objects themselves of course...) That can be a blessing or a curse, depending on your situation...
You can also use GroupBy like so:
var dict = myObjectsUnsorted.GroupBy(q => q.Category)
.ToDictionary(q => q.Key, w => new List<IMyObject>(w));
I am using ArrayList in Asp.net I want to extract specific items . My code is
ArrayList items = (ArrayList)Session["mycart"];
foreach(var v in items)
{
}
but this is not working . I want to get value like
v.myvalue;
My arralist is filled with several items coming from prevoius page.
The issue is that ArrayList stores all elements as object. You need to perform a cast to the type of object that contains myvalue.
For example
ArrayList items = (ArrayList)Session["mycart"];
foreach(var v in items)
{
MyObject o = v as MyObject;
if (o != null)
{
// do stuff with o.myvalue
}
}
It may be better to just use the generic List class rather ArrayList, although you may have a perfectly reason for doing otherwise. Generally, you should use the generic (e.g. List<MyObject>), not only for performance but also ease of use.
basically I'm building a very generic T4 template and one of the things I need it to do is say print variable.ToString(). However, I want it to evaluate lists and foreach through them and instead print ListItem.ToString() My T4 template does not know what type variable will be ahead of time, that is why this is so generic.
But my current code that gets generated looks like this:
if(variable!=null)
if(variable is IEnumerable) //error here
foreach(var item in variable)
Write(item.ToString());
I get a compiler error on the marked line for "Using the generic type System.Generic.Collections.IEnumerable requires one type argument"
I don't actually care what type it is though, I just want to know if you can foreach through the variable. What code should I use instead?
You have already accepted an answer however,since generic IEnumerable<T> implements the non generic IEnumerable you can just cast to that.
// Does write handle null? Might need some sanity aswell.
var enumerable = variable as System.Collections.IEnumerable;
if (enumerable != null)
foreach(var item in enumerable)
Write(item);
else
Write(item);
If you want to test for the non-generic IEnumerable then you'll need to include a using System.Collections directive at the top of your source file.
If you want to test for an IEnumerable<T> of some kind then you'll need something like this instead:
if (variable != null)
{
if (variable.GetType().GetInterfaces().Any(
i => i.IsGenericType &&
i.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
{
// foreach...
}
}
The other answers have pointed out the generic/non-generic IEnumerable difference but I should also point out that you will also want to test for String specifically because it implements IEnumerable but I doubt you'll want to treat it as a collection of characters.
Since C# 7.0 you can also achieve this so:
if (variable is IEnumerable enumVar)
{
foreach (var e in enumVar)
{
...
}
}
Well, somewhat simple but... if you only have:
using System.Collections.Generic;
you might need to add:
using System.Collections;
The former defines IEnumerable<T> and latter defines IEnumerable.
In general, with no non-generic base type/interface, this requires GetType and a recursive look-up through the base types/interfaces.
However, that doesn't apply here :-)
Just use the non-generic IEnumerable (System.Collections.IEnumerable), from which the generic IEnumerable (System.Collections.Generic.IEnumerable<T>) inherits.
You can actually test the base class of any generic type directly.
instance.GetGenericTypeDefinition() == typeof(IEnumerable<>)
If you don't care about object type and you are not in Generic method in C# 7.0+
if (item is IEnumerable<object> enumVar)
{
foreach (var e in enumVar)
{
e.ToString();
}
}
In C# < 7.0
if (item is IEnumerable<object>)
{
var enumVar = item as IEnumerable<object>;
foreach (var e in enumVar)
{
e.ToString();
}
//or you can cast an array to set values,
//since IEnumerable won't let you, unless you cast to IList :)
//but array version here
//https://stackoverflow.com/a/9783253/1818723
}
This is an old question, but I wanted to show an alternative method for determining if a SomeType is IEnumerable:
var isEnumerable = (typeof(SomeType).Name == "IEnumerable`1");
My question seems to be something easy, but I can't figure it out.
Let's say I have a "root" IEnumerable of objects. Each object has IEnumerable of strings. How can I obtain a single IEnumerable of those strings?
A possible solution is to do:
public IEnumerable<string> DoExample()
{
foreach (var c in rootSetOfObjects)
{
foreach (var n in c.childSetOfStrings)
{
yield return n;
}
}
}
But maybe there is a magic solution with Linq?
rootSetOfObjects.SelectMany(o => o.childSetOfStrings)
there is SelectMany in Linq that should work for you:
http://msdn.microsoft.com/en-us/vcsharp/aa336758.aspx#SelectManyCompoundfrom1
it definitely works on your collection and compound collections