I got an IEnumerator type from a ConcurrentDictionary . I am trying to iterate through it using the following way
System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<string,string>>
Ien = Concur_Dictionary.GetEnumerator();
foreach (KeyValuePair<string, string> pair in Ien) -->Error here
{
}
I get the following error
Error 4 foreach statement cannot operate on variables of type 'System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<string,string>>' because 'System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<string,string>>' does not contain a public definition for 'GetEnumerator'
Any suggestions on how I could iterate through this IEnumerator ?
You usually don't want to iterate through the IEnumerator; you just iterate over the IEnumerable directly:
foreach (var pair in Concur_Dictionary) …
If, for some reason, you don't have access to the IEnumerable, you can do this:
while (Ien.MoveNext())
{
var pair = Ien.Current;
…
}
You can use MoveNext() of it.
var enumerator = getInt().GetEnumerator();
while(enumerator.MoveNext())
{
//Line of codes..
}
You can do something like this.
Or this can be done.
foreach (var item in collection)
{
// do your stuff
}
Try this thing it worked for me.
Related
We ran in to performance issues and tracked it down to AutoMapper enumerating twice over an IEnumerable.
It's easily fixable on our side by simply feeding AutoMapper a List or Array, but I'm still curious if this is expected behavior.
The following minimal repro test fails::
[Test]
public void AutoMapper_Should_Not_Enumerate_Multiple_Times()
{
var counter = 0;
var values = Enumerable.Range(0, 3).Select(_ => counter++);
var mapper = new Mapper(new MapperConfiguration(_ => { }));
var dest= mapper.Map<int[]>(values);
Assert.Equal(3, counter);
}
Result: Counter = 6, dest = [3,4,5], which means the IEnumerable is iterated twice and the second iteration is returned.
I tried debugging this in AutoMapper, but I only figured out that something was first calling Count() and then iterating:
Is this expected behavior? How or where is an IEnumerable mapped to an Array and why is Count() called before iterating?
This is implemented by the ArrayMapper and the implementation is functionally this:
var count = source.Count();
var array = new TDestination[count];
int i = 0;
foreach (var item in source)
array[i++] = newItemFunc(item, context);
return array;
(hope everyone's well).
Please could I get some advice on how best to get a single string as a variable from the following foreach loop with razor (preferably not Linq)...
#if (selection.Any())
{
foreach(var item in selection){
foreach (var searchLocationItem in item.searchLocation)
{
if (!String.IsNullOrEmpty(searchLocationItem)){
counter++;
#searchLocationItem<text>,</text>;
}
}
}
}
The above code outputs a string exactly as I require, but as html, not a reusable variable.
Any help on how to get the result efficiently as a single string variable would be appreciated.
Regards,
You can use a stringbuilder:
StringBuilder builder = new StringBuilder();
foreach(var item in selection){
foreach (var searchLocationItem in item.searchLocation)
{
if (!String.IsNullOrEmpty(searchLocationItem)){
counter++;
builder.Append(String.Format("{0}<text>,</text>;", searchLocationItem));
}
}
}
#builder.ToString()
This is an interesting error I've come across while implementing IEnumerable on a class. It appears to be similar to an "access to modified closure" issue, but I'm at a loss as to how to fix it.
Here is a simple example that demonstrates the issue:
void Main()
{
var nodeCollection = new NodeCollection();
nodeCollection.MyItems = new List<string>() { "a", "b", "c" };
foreach (var node in nodeCollection)
{
node.Dump();
}
}
public class NodeCollection : IEnumerable<Node>
{
public List<string> MyItems;
public IEnumerator<Node> GetEnumerator()
{
// This isn't necessary, but it should prove that it's not an "access to modified closure" issue.
var items = MyItems;
for (var i = 0; i < 3; i++)
{
var node = new Node();
// I want the node to contains the items in MyItems.
node.Items = items;
// Plus an additional item. Note that I am adding the item to the node, NOT to MyItems.
node.Items.Add(string.Format("iteration: {0}", i));
yield return node;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class Node
{
public List<string> Items;
}
As you can see from the Dump() statement, I'm running this in LINQPad, but the issue will present itself in any IDE.
When I run the snippet, I get the following output:
Because I am adding the item to Items in the newly instantiated Node, I would NOT expect the item to be added to MyItems, but this is obviously what is occurring.
It seems that Items in Node is pointing to MyItems in NodeCollection.
Can anyone tell me:
Why this is happening?
How to make it not happen?
You are creating new nodes each iteration, but then setting the same items instance to the Items property of each node. Then you are adding the iteration string to the items instance stored in the Items collection (which is always the same instance), resulting in each subsequent node having more and more "iteration" entries. If you kept all of the nodes, you'd find that all of them have exactly the same Items value.
I think the basic misunderstanding here was that you were assuming that setting the Items property of the Node (node.Items = items;) would copy the items list into the node. In fact, all it does is set node.Items to point to the already-existing list that you call items.
This should give you an idea where you went wrong:
// This same instance of items is being reused each time
var items = MyItems;
for (var i = 0; i < 3; i++)
{
var node = new Node();
// I want the node to contains the items in MyItems.
// Assuming node.Items is a List<String>
node.Items = new List<String>();
node.Items.AddRange(items);
node.Items.Add(string.Format("iteration: {0}", i));
yield return node;
}
node.Items = items; sets node.Items to be a reference to the items list. There is just one list, with several references to it.
I suppose that what you want is to have a separate list in each node and that you want to copy the elements in items into that list. To do that, create a new list wich contains all of the elements from items.
node.Items = new List<string>(items);
When you do:
var item = MyItems;
you just create a reference to MyItems and store it in the variable item. Then when you do:
node.Items = items;
you just take the same reference and store it in node.Items. If you need node.Items to be a new list (point to a different memory location) initialize it again.
node.Items = new List();
In MonoTouch I need to process each object in an NSSet. My attempt, using Enumerate, is as follows:
public override void ReturnResults ( BarcodePickerController picker, NSSet results )
{
var n = results.Count; // Debugging - value is 3
results.Enumerate( delegate( NSObject obj, ref bool stop )
{
var foundCode = ( obj as BarcodeResult ); // Executed only once, not 3 times
if ( foundCode != null )
{
controller.BarcodeScannedResult (foundCode);
}
});
// Etc
}
Although the method is invoked with three objects in results, only one object is processed in the delegate. I would have expected the delegate to be executed three times, but I must have the wrong idea of how it works.
Unable to find any documentation or examples. Any suggestion much appreciated.
You have to set the ref parameter to false. This instructs the handler to continue enumerating:
if ( foundCode != null )
{
controller.BarcodeScannedResult (foundCode);
stop = false; // inside the null check
}
Here is the ObjC equivalent from Apple documentation.
Or you could try this extension method to make it easier..
public static class MyExtensions {
public static IEnumerable<T> ItemsAs<T>(this NSSet set) where T : NSObject {
List<T> res = new List<T>();
set.Enumerate( delegate( NSObject obj, ref bool stop ) {
T item = (T)( obj ); // Executed only once, not 3 times
if ( item != null ) {
res.Add (item);
stop = false; // inside the null check
}
});
return res;
}
}
Then you can do something like:
foreach(BarcodeResult foundCode in results.ItemsAs<BarcodeResult>()) {
controller.BarcodeScannedResult (foundCode);
}
Note: Keep in mind this creates another list and copies everything to it, which is less efficient. I did this because "yield return" isn't allowed in anonymous methods, and the alternative ways I could think of to make it a real enumerator without the copy were much much more code. Most of the sets I deal with are tiny so this doesn't matter, but if you have a big set this isn't ideal.
I have the following code which is in a base class.
MyApp.MyDB = new MyApp.MyDB ();
IRepository<T> repo = new SubSonicRepository<T>(db);
CurrentTable = repo.GetTable();
var s = db.SelectColumns(columnList.ToArray()).
From(CurrentTable.Name).
OrderAsc(CurrentTable.Descriptor.Name);
The idea is that all my classes can call this method.
I have just realised that I may need to a 'where' statement and there could be numerous columns names and values to test for.
What's the best approach for this?
UPDATE: I found this works below but is it best practice?
//WhereClause is a Dictionary<string, string>
int count = 0;
foreach (var whereitem in WhereClause)
{
if (count == 0)
{
s.Where(whereitem.Key).IsEqualTo(whereitem.Value);
}
else
{
s.And(whereitem.Key).IsEqualTo(whereitem.Value);
}
count++;
}
This simplifies the logic slightly: For the where clause, do something like this:
s.Where(1).IsEqualTo(1);
For all your other whereitem's, you can use And's.