Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Foreach statement cannot operate on variables of type 'object' because 'object' does not contain a public definition for 'GetEnumerator'

Tags:

c#

enumerate

I'm trying to figure out how to access values in an object through an API, but am having no luck. There is some documentation, but not a lot. I'm able to access some information, but what I'm looking for exists in a keyword field in a database that the software is using. I am able to print out the object type, but not the values in the actual object.

Here's my code:

 public class Test
    {
        public static ServiceConnection ConnectToDocuWare(Uri uri, string userName, string passWord)
        {
            return ServiceConnection.Create(uri, userName, passWord);
        }

        static void Main()
        {

            var userName;
            var passWord;
            var uri;
            var conn = ConnectToDocuWare(uri, userName, passWord);
            var org = conn.Organizations[0];
            var fileCabinets = org.GetFileCabinetsFromFilecabinetsRelation().FileCabinet;
            var fileCabinet = fileCabinets.SingleOrDefault(x => x.Name == "someValue");
            string documentID = "1";
            int DWID = int.Parse(documentID);
            string FCID = fileCabinet.Id;


            var dialogInfoItems = fileCabinet.GetDialogInfosFromDialogsRelation();
            var dialog = dialogInfoItems.Dialog.SingleOrDefault(x => x.DisplayName == "Some Value").GetDialogFromSelfRelation();
            var DocResults = RunQuery(dialog, documentID);


            foreach (Document doc in DocResults.Items)
            {
                var item = doc.GetDocumentFromSelfRelation();


                foreach (var itemInfo in item.Fields)
                {
                    if (itemInfo.ItemElementName.ToString() == "Keywords")
                    {
                        Console.WriteLine(itemInfo.Item);

                    }
                }
            }
        Console.ReadLine();
        }

        public static DocumentsQueryResult RunQuery(Dialog dialog, string DWDocID)
        {
            var q = new DialogExpression()
            {
                Operation = DialogExpressionOperation.And,
                Condition = new List<DialogExpressionCondition>()
                {
                    DialogExpressionCondition.Create("DWDOCID", DWDocID),
                },
                Count = 100,
                SortOrder = new List<SortedField>
                {
                    SortedField.Create("DWSTOREDATETIME", SortDirection.Desc)
                }
            };
            var queryResult = dialog.GetDocumentsResult(q);
            return queryResult;
        }
    }

This just outputs the object type. I've tried to use a foreach loop to output everything in the ItemInfo.Item object, but I get this error: Foreach statement cannot operate on variables of type 'object' because 'object' does not contain a public definition for 'GetEnumerator'

Essentially I'm trying to access the values in the keyword field to use later.

like image 485
Tom D Avatar asked Mar 08 '23 05:03

Tom D


1 Answers

The error message is very clear - you can only use a foreach loop on objects that have a public definition of the GetEnumerator method.

From the foreach, in (C# Reference) page in Microsoft docs:

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<T> interface.

This means that you can't use a foreach loop on any instance of any class (or struct) you want, because whatever is being used for the in part of the foreach loop must provide an enumerator.

Interesting fact: As Enigmativity pointed out in this answer, All you really need for a foreach loop to work is having a public method called GetEnumerator(), and have that public method returns an instance with a couple of methods and a property, namely void Reset(), bool MoveNext(), and T Current { get; private set; }, Where T is some type.

This means that you are not required to declare your class as implementing the IEnumerable or the IEnumerable<T> interface, And your Enumerator is not required to be declared as implementing the IEnumerator or IEnumerator<T> interface - it's sufficient that you provide the methods and properties defined it the relevant interfaces - That's all the c# compiler demands to use a foreach loop.

like image 160
Zohar Peled Avatar answered Apr 05 '23 23:04

Zohar Peled