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
}
}
Related
I want to get value in my object. When I look my inside of object, I can see my value in Result View IEnumerable. But, I can't get this values.
When I write "value."; just see "ToString, GetType, GetHashCode and Equals". I try GetType and get value but I can't. Because, I haven't name of values. How solve we this problem?
The IEnumerable uses syntactic sugar in the background. IEnumerable I feels like a list but behaves differently. The bigest different is that IEnumerable is lazy evaulated. This means only the requested object will be loaded into the memory. The interface hase a CurrentItem property that is accessed by foreach loop.
Here are some options to access the underlaying value:
User foreach
foreach (var value in myEnumerableCollection)
{
Console.WriteLine(value);
}
Use LINQ
var value = myEnumerableCollection.FirstOrDefault(x => x == someSearchTerm);
Cast the enumartion to a list and use the list methods and use indexers or other list methods to grab the value. A small warning, this will force the collection load every element into the memory. If it is large this may cause some issues. For example loading x million rows of db table with no pagination.
int index = 1;
var value = myEnumerableCollection.ToList()[index];
You can cast your value to IEnumerable T, where T - is your type, for example:
if (value is IEnumerable<int> resultList)
{
foreach (int item in resultList)
{
Console.WriteLine(item);
}
};
I am aware that the yield keyword indicates that the method in which it appears is an iterator. I was just wondering how that works with something like List<T>.AddRange.
Let's use the below example:
static void Main()
{
foreach (int i in MyInts())
{
Console.Write(i);
}
}
public static IEnumerable<int> MyInts()
{
for (int i = 0; i < 255; i++)
{
yield return i;
}
}
So in the above example after each yield, a value is returned in the foreach loop in Main and is printed to the console.
If we change Main to this:
static void Main()
{
var myList = new List<int>();
myList.AddRange(MyInts());
}
how does that work? Does AddRange get called for each int returned by the yield statement or does it somehow wait for all 255 values before adding the entire range?
The implementation of AddRange will iterate over the IEnumerable input using the iterator's .MoveNext() method until all values have been produced by your yielding method. This can be seen here.
So myList.AddRange(MyInts()); is called once and its implementation forces MyInts to return all of it values before moving on.
AddRange exhausts all values of the iterator because of how is implemented, but the following hypothetic method would only evaluate the first value of the iterator:
public void AddFirst<T>(IEnumerable<T> collection)
{
Insert(collection.First());
}
An interesting experiment while you play around with this is to add a Console.WriteLine(i); line in your MyInts method to see when each number is generated.
Short answer: When you call AddRange, it will internally iterate every item in your IEnumerable and add to the list.
If you did something like this:
var myList = new List<int>();
myList.AddRange(MyInts());
foreach (int i in myList)
{
Console.Write(i);
}
Then your values would be iterated twice, from the start to the end:
Once when adding to your list
Then in your for loop
Playing a bit
Now, let's suppose you created your own extension method for AddRange like this:
public static IEnumerable<T> AddRangeLazily<T>(this ICollection<T> col, IEnumerable<T> values)
{
foreach (T i in values)
{
yield return i; // first we yield
col.Add(i); // then we add
}
}
Then you could use it like this:
foreach (int i in myList.AddRangeLazily(MyInts()))
{
Console.Write(i);
}
...and it would be iterated twice as well, without going from the start to the end both times. It would lazily add each value to the list/collection and at the same time allow you to do something else (like printing it to output) after every new item being added.
If you had some sort of logic to stop the adding to the list in the middle of the operation, this should be helpful somehow.
The downside if this AddRangeLazily is: values will only be added to the collection once you iterate over AddRangeLazily like my code sample. If you just do this:
var someList = new List<int>();
someList.AddRangeLazily(MyInts());
if (someList.Any())
// it wouldn't enter here...
...it won't add values at all. If you wanted that behaviour, you should use AddRange. Forcing the iterationg over AddRangeLazily method would work, though:
var someList = new List<int>();
someList.AddRangeLazily(MyInts());
if (someList.AddRangeLazily(MyInts()).Count())
// it would enter here...thus adding all values to the someList
...however, depending on how lazy is the method you calling, it wouldn't iterate everything. For example:
var someList = new List<int>();
someList.AddRangeLazily(MyInts());
if (someList.AddRangeLazily(MyInts()).Any())
// it would enter here, plus adding only the first value to someList
Since Any() is true as soon as any item exists, then Any() just needs one iterationg to return true, therefore it just needs the first item to be iterated over.
I actually don't remember having to do something like this, it was just to play around with yield.
Fiddle here!!!
Interesting question.
The behavior is different if the enumerable is for a class that implements ICollection, such as another list or an array, but let's say it doesn't since your example doesn't. AddRange() simply uses the enumerator to insert items into the list one at a time.
using(IEnumerator<T> en = collection.GetEnumerator()) {
while(en.MoveNext()) {
Insert(index++, en.Current);
If the type of the enumerator is ICollection then AddRange first expands the list and then does a block copy.
If you want to see the code yourself:
https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,51decd510e5bfe6e
Why we can iterate item ex
mList.ForEach((item)
{
item.xyz ....
}
and for a simple array we need to force foreach loop?
foreach(int i in arr)
i.xyz
or use delegate type ?
Action<int> action = new Action<int>(myfunc);
Array.ForEach(intArray, action);
What is the differemce?
The first syntax is not correct. It should be like this:
mList.ForEach(item =>
{
// item.xyz
});
The ForEach is a method of List<T> that enables you for each item in a list to call an Action<T>.
On the other hand the foreach
statement repeats a group of embedded statements for each element in
an array or an object collection that implements the
System.Collections.IEnumerable or
System.Collections.Generic.IEnumerable interface.
That being said, ForEach can be called only on lists and foreach can be called on any object that implements either IEnumerable or IEnumerable. That's the big difference here.
Regarding the delegate type, there isn't any difference. Actually, lambda expressions item=>{ item.xyz = ...} are a shorthand for delegates.
The language defines foreach as an operation of IEnumerable. Therefore, everything which implements IEnumerable is iteratable. However, not all IEnumerables 'make sense' when using a ForEach block.
Take this for example:
public static IEnumerable<MyObject> GetObjects()
{
var i = 0;
while(i < 30)
yield return new MyObject { Name = "Object " + i++ };
}
And then you do something like this:
var objects = GetObjects();
objects.ForEach(o => o.Name = "Rob");
foreach (var obj in objects)
Console.WriteLine(obj.Name);
IF that compiled, it would print out Object 0 to Object 29 - NOT Rob 30 times.
The reason for this is that the iterator is reset each time you iterate the enumerable. It makes sense for ForEach on a list, as the enumerable has been materialized, and objects are not re-created every time you iterate it.
In order to make ForEach work on an enumerable, you'd need to materialize the collection as well (such as putting it into a list), but even that is not always possible, as you can have an enumerable with no defined end:
public static IEnumerable<MyObject> GetObjects()
{
while(true)
yield return new MyObject { Name = "Object " };
}
It also makes sense to have ForEach on Array - but for reasons I'm unaware of, it was defined as Array.ForEach(arr) rather than arr.ForEach()
Moral of the story is, if you think you need a ForEach block, you probably want to materialize the enumerable first, usually to a List<T> or an array (T[]).
A ListBox control has an Items property of type ListItemCollection.
I sort of understand why I can't write
foreach (var item in ShipperListBox.Items)
{
if (item.Selected) count++;
}
But instead have to write
foreach (ListItem item in ShipperListBox.Items)
{
if (item.Selected) count++;
}
It has to do with ListItemCollection implementing IEnumerable and not IEnumerable<ListItem> (as explained in this question).
But what I don't get is why the following is no problem.
for (int i = 0; i < ListBox1.Items.Count; i++)
{
if (ListBox1.Items[i].Selected) count++;
}
What part of ListItemCollection is making it clear to the compiler that ListBox.Items[i] is of type ListItem?
Because ListItemCollection implements an indexer that returns a ListItem.
This is separate from IEnumerable.
This is part of what .OfType<ListItem>() and .Cast<ListItem>() explicitly exist for:
The Cast(IEnumerable) method enables the standard query operators to be invoked on non-generic collections by supplying the necessary type information. For example, ArrayList does not implement IEnumerable, but by calling Cast(IEnumerable) on the ArrayList object, the standard query operators can then be used to query the sequence. (source)
So you can write
foreach (var item in ShipperListBox.Items.OfType<ListItem>())
{
if (item.Selected) count++;
}
I couldn't tell you why, though.
ListItemCollection.GetEnumerator does return an enumerator which was used since .NET 1.0 which does return object as value. The foreach pattern (as Eric Lippert does explain in much greater detail) requires an Enumerator returned by the object via the GetEnumerator method.
When you use var the compiler infers the type of you loop variable as object since Current of the Enumerator does return only an object.
public interface IEnumerator
{
bool MoveNext();
object Current { get; }
void Reset();
}
But when you use foreach(ListItem item in xxx) ... the compiler does add a cast to ListItem from object automatically for you. You can try it out when you do a foreach(string str in new object[] { "str", 1 }) which will result in an InvalidCastException. There is no magic going with the var keyword. It simply does infer the type without doing any extra magic.
When you expect a ListItem in your loop you should write it out clearly. From the method signature of the enumerator it is not clear what objects it will return. You have to tell the compiler which types you expect. One more reason to not use the var keyword since the readers of your code will also not be able to deduce the type of your looping variable as well.
I have a foreach loop that needs converting to a for or while loop. My loop looks like this:
foreach (Item item in Items)
{
// some stuff
}
What is the equivalent for or while loop?
I think I need to use GetEnumerator to get an IEnumerator<Item>, but I don't know how to use it properly. Items isn't a list, otherwise I'd use indexing.
In the simplest case(no disposing etc.) you can use:
var enumerator = Items.GetEnumerator();// `var` to take advantage of more specific return type
while(enumerator.MoveNext())
{
Item item = enumerator.Current;
...
}
For the exact rules check the C# specification 8.8.4 The foreach statement.
A foreach statement of the form
foreach (V v in x) embedded-statement
is then expanded to:
{
E e = ((C)(x)).GetEnumerator();
try {
V v;
while (e.MoveNext()) {
v = (V)(T)e.Current;
embedded-statement
}
}
finally {
… // Dispose e
}
}
(Quoted from the C# Language Specification Version 4.0)
The types using here are: "a collection type C, enumerator type E and element type T". E is the return type of GetEnumerator, and not necessarily IEnumerator<V> since foreach uses duck typing. The spec also describes a number of corner cases and how to infer these types, but those details are probably not relevant here.
In C# 5 the declaration of v will be moved into the while loop to get more intuitive closure semantics.
If you're going to use a for loop, it generally means there's some way of quickly accessing the n-th item (usually an indexer).
for(int i = 0; i < Items.Count; i++)
{
Item item = Items[i]; //or Items.Get(i) or whatever method is relevant.
//...
}
If you're just going to access the iterator, you usually just want to use a foreach loop. If, however, you can't, this is usually the model that makes sense:
using(IEnumerator<Item> iterator = Items.GetEnumerator())
while(iterator.MoveNext())
{
Item item = iterator.Current;
//do stuff
}
you could, technically, do this in a for loop, but it would be harder because the construct just doesn't align well with this format. If you were to discuss the reason that you can't use a foreach loop we may be able to help you find the best solution, whether or not that involves using a for loop or not.
This is an equivalent in a for-loop
for (IEnumerator i = Items.GetEnumerator(); i.MoveNext(); )
{
Item item = (Item)i.Current;
// some stuff
}