Using foreach to iterate through each member of nested classes
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 15

Thread: Using foreach to iterate through each member of nested classes

  1. #1
    Join Date
    May 2010
    Location
    .Net 4.0
    Posts
    58

    Using foreach to iterate through each member of nested classes

    Hello,

    I have a class called Residue which contains a list of a class called Atom. I'm trying to use foreach to display all of the contents of every Residue which I have, but I'm getting the following error:

    Error 1 foreach statement cannot operate on variables of type 'NOEAssign.Residue' because 'NOEAssign.Residue' does not contain a public definition for 'GetEnumerator' .

    I'm not sure how to use the enumerator to fix this; could I please get an idea? Here's my code:

    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Collections;
    
    namespace NOEAssign
    {
        class MainProg
        {
            static void Main()
            {
    
                List<Residue> Residues = new List<Residue>();
                Residues = ReadShifts.GetShifts();
                Residues.GetEnumerator();
    
                foreach (Residue resi in Residues)
                {
                    foreach (Atom particle in resi) //PROBLEM IN THIS LINE
                    {
                        Console.WriteLine("{0}, {1}", particle.name, particle.Shift);
                        Console.ReadLine();
                    }
                }
            }
        }
    
        public class Atom
        {
            public Atom(string name, double Shift)
            {
                this.name = name;
                this.name.GetEnumerator();
                this.Shift = Shift;
            }
            public string name { get; set; }
            public double Shift { get; set; }
        }
    
        public class Residue
        {
            public Residue(string name)
            {
                Atoms = new List<Atom>();
                Atoms.GetEnumerator();
            }
            public List<Atom> Atoms { get; set; }
        }
    }
    P.S. This is the same project which I asked about in an earlier thread, but in that thread I think I confused myself as to what I was actually asking for. The project has progressed since then and I've hit this new barrier. Help would be appreciated.

  2. #2
    Join Date
    Mar 2004
    Location
    Prague, Czech Republic, EU
    Posts
    1,701

    Re: Using foreach to iterate through each member of nested classes

    The error message is self-descriptive. You have to implment required interface:
    Code:
    public class Residue : IEnumerable<Atom>
        {
            public Residue(string name)
            {
                Atoms = new List<Atom>();
            }
            public List<Atom> Atoms { get; set; }
    
            public IEnumerable<Atom> GetEnumerator()
            {
               return this.Atoms.GetEnumerator();
            }
        }
    • Make it run.
    • Make it right.
    • Make it fast.

    Don't hesitate to rate my post.

  3. #3
    Join Date
    May 2010
    Location
    .Net 4.0
    Posts
    58

    Re: Using foreach to iterate through each member of nested classes

    Thanks for the help. I implemented your code and tried to implement the interface as described in: http://support.microsoft.com/kb/322022

    I'm having an issue though. Where the msdn example has an array, I have a list and I don't know what the required syntax is for it. Here is my updated Residue class, which has comments on where I don't get the syntax:

    Code:
        public class Residue : IEnumerable<Atom>
    
        {
            public Residue(string name)
            {
                Atoms = new List<Atom>();
            }
    
            int position = -1;
    
            public List<Atom> Atoms { get; set; }
            
            public IEnumerator<Atom> GetEnumerator()
            {
                return this.Atoms.GetEnumerator();
            }
    
            public IEnumerator<Atom> GetEnumerator()
            {
                return (IEnumerator<Atom>)this;
            }
    
            public bool MoveNext()
            {
                position++;
                //return (position < WHAT DO I PUT HERE?);
            }
    
            public void Reset()
            {//WHAT DO I PUT HERE? = 0;}
            }
    
            public object Current
            {
                //get {return WHAT DO I PUT HERE?}
            }
        }

  4. #4

    Re: Using foreach to iterate through each member of nested classes

    why not just in inherit from list and have all your problems solved?

  5. #5
    Join Date
    May 2010
    Location
    .Net 4.0
    Posts
    58

    Re: Using foreach to iterate through each member of nested classes

    Quote Originally Posted by matthewsanford@gmail.com View Post
    why not just in inherit from list and have all your problems solved?
    I'm sorry, could you please elaborate? I'm a biochemist, not a programmer

  6. #6

    Re: Using foreach to iterate through each member of nested classes

    Well you are directly exposing your list with get set methods so I assume that you want to be able to access the list and all of its methods and you are not trying to wrap it. If it were me I would just inherit from list and then add whatever methods etc that I wanted

    Code:
    public class Residue : List<Atom>
    {
    
    }
    Problem solved you can now use the foreach statment.

  7. #7
    Join Date
    May 2010
    Location
    .Net 4.0
    Posts
    58

    Re: Using foreach to iterate through each member of nested classes

    Like this?

    Code:
        public class Residue : List<Atom>
    
        {
            public Residue(string name)
            {
                Atoms = new List<Atom>();
            }
    
            public List<Atom> Atoms { get; set; }
        }
    Then I still have to write the dispose, current, and reset interfaces, and I'm not sure how to do that because my atoms are in a list rather than an array.

  8. #8

    Re: Using foreach to iterate through each member of nested classes

    no, when you inherit YOU ARE A LIST so you have the add methods and everything already as part of you members, if you need dispose you need to implement IDisposable. I have written an example that shows you how to use the class

    Code:
        public class Atom
        {
            public Atom(string name)
            {
                this.name = name ;
            }
    
            string name ;
            public string Name
            {
                get {return name;}
            }
        }
    
        public class Residue
            : List<Atom>, IDisposable
        {
    		/// <summary>
    		/// Releases unmanaged resources and performs other cleanup operations before the
    		/// <see cref="Disposable"/> is reclaimed by garbage collection.
    		/// </summary>
            ~Residue()
    		{
    			Dispose(false);
    		}
    
            private bool disposed = false;
            /// <summary>
            /// Releases unmanaged and - optionally - managed resources
            /// </summary>
            /// <param name="disposeManaged"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
            private void Dispose(bool disposeManaged)
            {
                if (this.disposed)
                    return;
                if (disposeManaged)
                    OnDisposeManagedResources();
                OnDisposeUnManagedResources();
            }
    
            /// <summary>
            /// Called when managed resources should be disposed.
            /// </summary>
            protected virtual void OnDisposeManagedResources()
            {
            }
    
            /// <summary>
            /// Called when unmanaged resources should be disposed.
            /// </summary>
            protected virtual void OnDisposeUnManagedResources()
            {
            }
    
            #region IDisposable Members
    
            /// <summary>
            /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
            /// </summary>
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
    
            #endregion
    
        }
    
        static void Main()
        {
            Residue residue = new Residue();
    
            residue.Add(new Atom("Some Atom"));
            residue.Add(new Atom("Another Atom"));
            residue.Add(new Atom("Yet Another Atom"));
            foreach (Atom atom in residue)
                Console.WriteLine("Atom: " + atom.Name) ;
            residue.Dispose();
        }
    I hope this makes sense

  9. #9
    Join Date
    May 2010
    Location
    .Net 4.0
    Posts
    58

    Re: Using foreach to iterate through each member of nested classes

    Wow, looks like I'm going to have to break out the C# guide again. Your code worked perfectly; now I have to understand it and manipulate it. Thanks for your help!

  10. #10
    Join Date
    Jun 2008
    Posts
    2,477

    Re: Using foreach to iterate through each member of nested classes

    BTW, you don't need to implement IDisposable unless you have some unmanaged resources that you are maintaining within your class (images, native file handles, DB connections, etc.)
    If you liked my post go ahead and give me an upvote so that my epee.... ahem, reputation will grow.

    Yes; I have a blog too - http://the-angry-gorilla.com/

  11. #11
    Join Date
    May 2010
    Location
    .Net 4.0
    Posts
    58

    Re: Using foreach to iterate through each member of nested classes

    Is there a way to reset the foreach counter? I have a nested foreach loop in which the inner loop goes through the same list as the outer loop. However, when it's going through the code, the inner loop picks up right where the outer loop leaves off, as evidenced in the attached picture. Here is the relevant code:

    Code:
    foreach (Residue resi in Residues)
                    {
                        if (resi.name != olddisplayname)//trying to make system to make display clearer
                        {
                            Console.WriteLine("Searching in {0}", resi.name);
                            olddisplayname = resi.name;
                        }
                        string heavytype = "";
                        foreach (Atom particle in resi)
                        {
                            Console.WriteLine("Now examining {0} {1}", resi.name, particle.name);
                            if (particle.Shift > Hevlowerbound && particle.Shift < Hevupperbound)
                            {
                                heavytype = particle.type;
                                Console.WriteLine("Now searching between {0} and {1} because {2} contains {3} at {4}", Plowerbound, Pupperbound, resi.name, particle.name, particle.Shift);
                                //diagnostic
                                if (linecounter == 84)
                                {
                                    Console.WriteLine("Match should be found at this residue because it contains {2} {3}. Heavy atom is now set to {1} {0}", particle.name, resi.name, resi.name, particle.name);
                                }
                                foreach (Atom particle2 in resi)
                                {
                                    //diagnostic
                                    if (linecounter == 84)
                                    {
                                        Console.WriteLine("Now looking at {0} {1}", resi.name, particle2.name);
                                        //Console.WriteLine("LowerBound: {0} Upperbound: {1} Shift: {2} Heavy type: {3} Current type: {4} Heavy Name: {5} Light Name: {6}", Plowerbound, Pupperbound, particle2.Shift, heavytype, particle2.type, particle.name, particle2.name);
                                    }
                                    if (particle2.Shift > Plowerbound && particle2.Shift < Pupperbound && particle2.type == heavytype && particle2.name != particle.name)
                                    {
                                        Match currentmatch = new Match();
                                        currentmatch.Resiname = resi.name;
                                        currentmatch.HeavyName = particle.name;
                                        currentmatch.HeavyPPM = particle.Shift;
                                        currentmatch.ProtonName = particle2.name;
                                        currentmatch.ProtonPPM = particle2.Shift;
                                        currentmatch.NumberInNOAlist = peak.NumInList;
                                        Console.WriteLine("Match found!");
                                        Matches.Add(currentmatch);
                                    }
                                    else { Console.WriteLine("No match was found."); }
                                }
                            }
                            else { Console.WriteLine("The shift of {0} {1} was not within the desired bounds", resi.name, particle.name); if (linecounter == 84) { Console.ReadLine(); } }
                        }
                    }
                }
    As the picture shows, the only atom that the inner foreach loop loads into particle2 is CG2. I need it to go all the way from CA until the end of all of the atoms in I60. Am I missing a command to reset the loop, or is my logic wrong?
    Attached Images Attached Images  

  12. #12

    Re: Using foreach to iterate through each member of nested classes

    use a for loop on your inner loop, see the sub section of your code below

    Code:
                      foreach (Atom particle in resi)
                        {
                            Console.WriteLine("Now examining {0} {1}", resi.name, particle.name);
                            if (particle.Shift > Hevlowerbound && particle.Shift < Hevupperbound)
                            {
                                heavytype = particle.type;
                                Console.WriteLine("Now searching between {0} and {1} because {2} contains {3} at {4}", Plowerbound, Pupperbound, resi.name, particle.name, particle.Shift);
                                //diagnostic
                                if (linecounter == 84)
                                {
                                    Console.WriteLine("Match should be found at this residue because it contains {2} {3}. Heavy atom is now set to {1} {0}", particle.name, resi.name, resi.name, particle.name);
                                }
                                Atom particle2
                                for (int i=0; i<resi.Count; i++)
                                {
                                    particle2 = resi[i] ;
    Last edited by matthewsanford@gmail.com; June 18th, 2010 at 08:33 AM.

  13. #13
    Join Date
    May 2010
    Location
    .Net 4.0
    Posts
    58

    Re: Using foreach to iterate through each member of nested classes

    I used the for loop and am getting the exact same results. I used the simple inner loop:

    Code:
    Atom particle2
                                for (int i=0; i<resi.Count; i++)
                                {
                                    particle2 = resi[i] ;
                                    Console.WriteLine(particle2.name);
                                 }
    I know for a fact that when linecounter = 84 (from my previously posted code), the outer loop is supposed to hit a match at residue I60 atom CG2. It is then supposed to search through all atoms of the current residue (I60) using the new parameters (Plowerbound and Pupperbound) and should find a match at HG2*. I checked the file I'm searching for and numerically it works out. However, the output I'm getting looks as follows:

    Searching in I60
    Now examining I60 CA
    The shift of I60 CA was not within the desired bounds

    Searching in I60
    Now examining I60 CB
    The shift of I60 CB was not within the desired bounds

    Searching in I60
    Now examining I60 CD1
    The shift of I60 CD1 was not within the desired bounds

    Searching in I60
    Now examining I60 CG1
    The shift of I60 CG1 was not within the desired bounds

    Searching in I60
    Now examining I60 CG2
    Now searching between 0.91 and 0.99 because I60 contains CG2 at 18.073
    Match should be found at this residue because it contains I60 CG2. Heavy atom is now set to I60 CG2
    CG2 ///should iterate from CA all the way through the Cs and Hs and N!
    Now examining I60 HA
    The shift of I60 HA was not within the desired bounds
    ...

    As you can see, the code is still not iterating through all of the atoms. Also, when I put Console.WriteLine(Resi.count); within my ForEach (Atom particle in Resi), it writes "1", while doing Console.WriteLine(Residues.count) gives 1023, which is the total number of all atoms in all residues. I'm completely confused as to why it's doing this. Any tips?
    Last edited by Danja91; June 18th, 2010 at 01:49 PM.

  14. #14

    Re: Using foreach to iterate through each member of nested classes

    You can not compare strings using the == or the != operator. the == operator and the != operator simply compare to see if the object are the same object, not if the object has the same value. you need to use string.Compare(particale1.Name, particale2.Name)!=0, since strings are immutable they will never be the same object.

    Same goes for the particale2.Type == HeavyType statment. If HeavyType is a class and the two are not exactly the same object instance this will always evaluate to be false. You need to override the Equals method and use those to evaluate if they are different objects but the same (if that makes any sense). Could you post more code, there is not enough there to completly see the problem.

    I will say this if you know that
    particle2.Shift > Plowerbound && particle2.Shift < Pupperbound is true

    then it must be some part of
    particle2.type == heavytype && particle2.name != particle.name

    is evaluating to false.

    You seem to be making this much more complicated than it needs to be. Why not make a simple search function in the residue class that finds all the atoms that have a given Shift range then search for the Hev and then search for the corresponding P types. I wrote a short example, I did not know what to do with the "HeavyType" thing since I have no refrence as to what that is but you can just include that as part of your search routine

    Code:
        class Atom
        {
            public Atom(string name, double shift)
            {
    
            }
    
            string name;
            public string Name
            {
                get { return name; }
            }
    
            double shift;
            public double Shift
            {
                get { return shift; }
            }
        }
    
        class Residue
            : List<Atom>
        {
            public Atom[] FindShiftRange(double lower, double upper)
            {
                return FindShiftRange(lower, upper, null);
            }
    
            public Atom[] FindShiftRange(double lower, double upper, Atom atomstoexclude)
            {
                List<Atom> list = new List<Atom>();
    
                foreach (Atom a in list)
                {
                    if (a!=atomstoexclude && a.Shift < upper && a.Shift > lower)
                        list.Add(a);
    
                }
                return list.ToArray();
            }
        }
    Btw you may notice that I do a != on two objects in my search loop but that is because I do want to make sure that it is not the "same" object in that case.

    A quick tip, put a break point on that if statement, then drag each part of the if statement into your watch window, it will tell you if that part is evaluating to be true or false.

    further I am confused as to why you are doing what you are doing, if you want to search for a particular atom with an upper and lower bound partical shift in a residue why not make that a method within the the residue class
    Last edited by matthewsanford@gmail.com; June 18th, 2010 at 03:03 PM.

  15. #15
    Join Date
    May 2010
    Location
    .Net 4.0
    Posts
    58

    Re: Using foreach to iterate through each member of nested classes

    Thanks for the help!

    I didn't write the search routines because I'm a bad programmer and I didn't think of putting any search methods within the class. I'm definitely going to play with that tonight; it looks easier than what I'm doing.

    I found my fundamental problem though. My ReadShifts function, which I had considered to be rock solid, was actually bad. When I was testing it, I wrote the diagnostics to report as the shifts were being written, and it appeared everything was correct. However, when I took the time to write a diagnostics function using the full list returned by ReadShifts, I had it tell me the name of each residue followed by each atom within the residue, and the results looked like this:

    Residue #596: I60.
    Atoms:
    CA

    Residue #597: I60
    Atoms:
    CB

    It turned out I was careless and ended up making a residue per atom. I think that pretty much sums up my programming prowess . To be fair, I only started learning about a month ago.

    Anyway, thank you for all of your suggestions. They really helped!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center