locked
how to return value from function that containing while? RRS feed

  • Question

  • Hi, i'm new to programming.

    i'm having problem to return value from a function that containing while loop. my expectation is when i call the function from other function, it'll always change it values. here it goes

        {
            static int a;
            
            public static int func1()
            {
                a = 0;
                while (true)
                {
                    a++;
                    return a;
                }
            }
            public static void Main()
            {
                int b = func1();
                Console.WriteLine(b);
                Console.ReadLine();
            }
        }
    in this code the result is only '1' (it's not looping), what i want is the loop is working everytime and sending the 'a' value to main function. sorry for botherin' everyone with this basic question.
    Monday, March 5, 2012 9:06 AM

Answers

  • hmm, maybe you want something line a "yield return"?

            public static IEnumerable<int> func1()
            {
                a = 0;
                while (true)
                {
                    a++;
                    yield return a;
                }
            }
            public static void Main()
            {
                foreach(int b in func1()) {
                  Console.WriteLine(b);
                  Console.ReadLine();
                }
            }

    Edit:

    Besides: YOUR funcion always sets a to 0... the func1 is always finished with a return. You could remove the while(true) from the func1 and also remove the "a=0;", then it may work...

    • Edited by GreatVolk Monday, March 5, 2012 9:18 AM
    • Marked as answer by Jason Dot Wang Friday, March 23, 2012 6:38 AM
    Monday, March 5, 2012 9:17 AM
  • You can use yield return statement. You need to change func1 declaration to following, I also used end value to avoid looping forever. You need to loop the values returned by func1 in the Main method.

            static void Main(string[] args)
            {
                foreach (int value in func1(10))
                {
                    Console.WriteLine(value);
                }
    
                Console.ReadKey();
            }
    
            static IEnumerable<int> func1(int end)
            {
                int a = 0;
    
                while (a < end)
                {
                    a++;
                    yield return a;
                }
            }

    More aboud yield return, see http://msdn.microsoft.com/en-us/library/9k7k7cf0(v=vs.100).aspx




    • Edited by MasaSam Monday, March 5, 2012 9:23 AM
    • Marked as answer by Jason Dot Wang Friday, March 23, 2012 6:38 AM
    Monday, March 5, 2012 9:20 AM
  • Hi e-free-thing,

      You need to use IEnumerable generic and its iterators,and you need to limit a condition until the condition doesn't meet and exit to the loop. Furthermore, I give you the explanation coming from CSharp4.0 in a Nutshell.

      Whereas a return statement expresses "Here's the value you asked me to return from this method," a yield return statement expresses "Here's the next element you asked me to yield from this enumerator."On each yield statement, control is returned to the caller, but the callee's state is maintained so that the method can continue executing as soon as the caller enumerates the next element. The lifetime of this state is bound to the enumerator, such that the state can be released when the caller has finished enumerating.

      By contrast, if you want to exit to the loop,you need to use yield break.

      Sincerely,

      Jason Wang


    orichisonic http://blog.csdn.net/orichisonic If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".


    Tuesday, March 6, 2012 4:58 AM

All replies

  • hmm, maybe you want something line a "yield return"?

            public static IEnumerable<int> func1()
            {
                a = 0;
                while (true)
                {
                    a++;
                    yield return a;
                }
            }
            public static void Main()
            {
                foreach(int b in func1()) {
                  Console.WriteLine(b);
                  Console.ReadLine();
                }
            }

    Edit:

    Besides: YOUR funcion always sets a to 0... the func1 is always finished with a return. You could remove the while(true) from the func1 and also remove the "a=0;", then it may work...

    • Edited by GreatVolk Monday, March 5, 2012 9:18 AM
    • Marked as answer by Jason Dot Wang Friday, March 23, 2012 6:38 AM
    Monday, March 5, 2012 9:17 AM
  • You can use yield return statement. You need to change func1 declaration to following, I also used end value to avoid looping forever. You need to loop the values returned by func1 in the Main method.

            static void Main(string[] args)
            {
                foreach (int value in func1(10))
                {
                    Console.WriteLine(value);
                }
    
                Console.ReadKey();
            }
    
            static IEnumerable<int> func1(int end)
            {
                int a = 0;
    
                while (a < end)
                {
                    a++;
                    yield return a;
                }
            }

    More aboud yield return, see http://msdn.microsoft.com/en-us/library/9k7k7cf0(v=vs.100).aspx




    • Edited by MasaSam Monday, March 5, 2012 9:23 AM
    • Marked as answer by Jason Dot Wang Friday, March 23, 2012 6:38 AM
    Monday, March 5, 2012 9:20 AM
  • Hi, 

    What i see is you declared variable a,  as static, so i guess you don't need to yield the value of a in while(true), you can simply have a call

    	static int a = 0;
            public static int func1()
            {
                return a++;
            }
            public static void Main()
            {
                Console.WriteLine(func1());
                Console.WriteLine(func1());
                Console.ReadLine();
            } 

     

    If this post answers your question, please click "Mark As Answer". If this post is helpful please click "Mark as Helpful".

    • Proposed as answer by servy42 Monday, March 5, 2012 4:10 PM
    • Marked as answer by Jason Dot Wang Friday, March 23, 2012 6:36 AM
    • Unmarked as answer by Jason Dot Wang Friday, March 23, 2012 6:37 AM
    Monday, March 5, 2012 9:57 AM
  • Kris' answer will work in a single threaded app, but it's not threadsafe, and static methods, by convention, should be threadsafe.  If you know it's not an issue you might just want to add a comment to that effect.
    Monday, March 5, 2012 4:11 PM
  • Hi e-free-thing,

      You need to use IEnumerable generic and its iterators,and you need to limit a condition until the condition doesn't meet and exit to the loop. Furthermore, I give you the explanation coming from CSharp4.0 in a Nutshell.

      Whereas a return statement expresses "Here's the value you asked me to return from this method," a yield return statement expresses "Here's the next element you asked me to yield from this enumerator."On each yield statement, control is returned to the caller, but the callee's state is maintained so that the method can continue executing as soon as the caller enumerates the next element. The lifetime of this state is bound to the enumerator, such that the state can be released when the caller has finished enumerating.

      By contrast, if you want to exit to the loop,you need to use yield break.

      Sincerely,

      Jason Wang


    orichisonic http://blog.csdn.net/orichisonic If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".


    Tuesday, March 6, 2012 4:58 AM
  • thanks guys i really appreciate it. ok rrr...actually, i'm using .net micro framework. yes it's FEZ panda ii microcontroller from GHI electronics, sadly not all the feature from visual c# can be used in NMF. for example multidimensional array and jagged array is not supported. and unfortunately, System.Collections is collide with System.Threading, and i got this error "Missing compiler required member 'System.Threading.Thread.get_ManagedThreadId'" you can see my code below

    using System;
    using System.Collections;
    using System.Threading;
    using Microsoft.SPOT;
    using Microsoft.SPOT.Hardware;
    using GHIElectronics.NETMF.Hardware;
    using GHIElectronics.NETMF.FEZ;
    
    namespace FEZ_Touch_Example
    {
        public class Program
        {
            static FEZ_Components.FEZTouch lcd;
    
            public static IEnumerable MyThread() // this is suppose to be another thread but i turn it down for a while due to the development
            {
                AnalogIn lightSensor = new AnalogIn((AnalogIn.Pin)FEZ_Pin.AnalogIn.An2);
                AnalogIn tempSensor = new AnalogIn((AnalogIn.Pin)FEZ_Pin.AnalogIn.An3);
                bright = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di0, false);
                dimm = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di1, false);
                lightSensor.SetLinearScale(0, 100);
                tempSensor.SetLinearScale(10, 40);
    
                int lightSensorReading = 0;
                int tempSensorReading = 0;
                while (true)
                {
                    lightSensorReading = lightSensor.Read();
                    tempSensorReading = tempSensor.Read();
    
                    Thread.Sleep(300);
                    yield return lightSensorReading; //i only return one value just for test
                }
            }
    
            public static void MyThread1()
            {
                // This is for FEZ Panda II
                FEZ_Components.FEZTouch.LCDConfiguration lcdConfig = new FEZ_Components.FEZTouch.LCDConfiguration(FEZ_Pin.Digital.Di28, FEZ_Pin.Digital.Di20, FEZ_Pin.Digital.Di22, FEZ_Pin.Digital.Di23, new FEZ_Pin.Digital[8] { FEZ_Pin.Digital.Di51, FEZ_Pin.Digital.Di50, FEZ_Pin.Digital.Di49, FEZ_Pin.Digital.Di48, FEZ_Pin.Digital.Di47, FEZ_Pin.Digital.Di46, FEZ_Pin.Digital.Di45, FEZ_Pin.Digital.Di44 }, FEZ_Pin.Digital.Di24, FEZ_Pin.Digital.Di26);
                FEZ_Components.FEZTouch.TouchConfiguration touchConfig = new FEZ_Components.FEZTouch.TouchConfiguration(SPI.SPI_module.SPI2, FEZ_Pin.Digital.Di25, FEZ_Pin.Digital.Di34);
    
                lcd = new FEZ_Components.FEZTouch(lcdConfig, touchConfig);
    
                InitGraphics();
    
                lcd.TouchDownEvent += new FEZ_Components.FEZTouch.TouchEventHandler(button_TouchDownEvent);
                lcd.TouchUpEvent += new FEZ_Components.FEZTouch.TouchEventHandler(button_TouchUpEvent);
                lcd.TouchMoveEvent += new FEZ_Components.FEZTouch.TouchEventHandler(lcd_TouchMoveEvent);
                lcd.TouchDownEvent += new FEZ_Components.FEZTouch.TouchEventHandler(lcd_TouchDownEvent);
                lcd.TouchUpEvent += new FEZ_Components.FEZTouch.TouchEventHandler(lcd_TouchUpEvent);
                
            }
    
            public static void Main()
            {
                Thread lcdThread2;
                lcdThread2 = new Thread(MyThread1);
                lcdThread2.Start();
    
                Thread.Sleep(Timeout.Infinite);
            }
    
            const int BANNER_HEIGHT = 20;
            const int BUTTON1_HEIGHT = 60 - BANNER_HEIGHT;
            const int BUTTON2_HEIGHT = 100 - BANNER_HEIGHT;
    
            public static void InitGraphics()
            {
                // banner
                lcd.FillRectangle(0, 0, FEZ_Components.FEZTouch.ScreenWidth, BANNER_HEIGHT, FEZ_Components.FEZTouch.Color.Blue);
                string ban1 = "Britantyo Sensor Reader v1.0";
                lcd.DrawString(ban1, (FEZ_Components.FEZTouch.ScreenWidth - ban1.Length * FEZ_Components.FEZTouch.FONT_WIDTH) / 2, 0, FEZ_Components.FEZTouch.Color.Red, FEZ_Components.FEZTouch.Color.Black);
    
                // drawing area
                lcd.FillRectangle(0, BANNER_HEIGHT, FEZ_Components.FEZTouch.ScreenWidth, FEZ_Components.FEZTouch.ScreenHeight - BANNER_HEIGHT, FEZ_Components.FEZTouch.Color.White);
    
                // For monitoring sensor
                lcd.FillRectangle(20, BUTTON1_HEIGHT - 5, 72, 25, FEZ_Components.FEZTouch.Color.Cyan);
                lcd.DrawString(" Monitor ", 20, BUTTON1_HEIGHT, FEZ_Components.FEZTouch.Color.Black, FEZ_Components.FEZTouch.Color.Cyan);
    
                // For sensor adjustment
                lcd.FillRectangle(20, BUTTON2_HEIGHT - 5, 72, 25, FEZ_Components.FEZTouch.Color.Cyan);
                lcd.DrawString(" Setting ", 20, BUTTON2_HEIGHT, FEZ_Components.FEZTouch.Color.Black, FEZ_Components.FEZTouch.Color.Cyan);
    
                // Showing sensorvalue on LCD
                IEnumerable Datas = MyThread();
                lcd.DrawString(Datas.ToString(), 20, 280, FEZ_Components.FEZTouch.Color.Black, FEZ_Components.FEZTouch.Color.White);
                
            static void button_TouchDownEvent(int x, int y)
            {
                if (x >= 20 & x <= 92 & y >= (BUTTON1_HEIGHT - 5) & y <= (BUTTON1_HEIGHT + 20))
                {
                    // button1 touch
                    lcd.FillRectangle(20, BUTTON1_HEIGHT - 5, 72, 25, FEZ_Components.FEZTouch.Color.Blue);
                    lcd.DrawString(" Monitor ", 20, BUTTON1_HEIGHT, FEZ_Components.FEZTouch.Color.Red, FEZ_Components.FEZTouch.Color.Blue);
                }
                else if (x >= 20 & x <= 92 & y >= (BUTTON2_HEIGHT - 5) & y <= (BUTTON2_HEIGHT + 20))
                {
                    // button2 touch
                    lcd.FillRectangle(20, BUTTON2_HEIGHT - 5, 72, 25, FEZ_Components.FEZTouch.Color.Blue);
                    lcd.DrawString(" Setting ", 20, BUTTON2_HEIGHT, FEZ_Components.FEZTouch.Color.Red, FEZ_Components.FEZTouch.Color.Blue);
                }
            }
    
            static void button_TouchUpEvent(int x, int y)
            {
                if (x >= 20 & x <= 92 & y >= (BUTTON1_HEIGHT - 5) & y <= (BUTTON1_HEIGHT + 20))
                {
                    // button1 release
                    lcd.FillRectangle(20, BUTTON1_HEIGHT - 5, 72, 25, FEZ_Components.FEZTouch.Color.Cyan);
                    lcd.DrawString(" Monitor ", 20, BUTTON1_HEIGHT, FEZ_Components.FEZTouch.Color.Black, FEZ_Components.FEZTouch.Color.Cyan);
                }
                else if (x >= 20 & x <= 92 & y >= (BUTTON2_HEIGHT - 5) & y <= (BUTTON2_HEIGHT + 20))
                {
                    // button1 release
                    lcd.FillRectangle(20, BUTTON2_HEIGHT - 5, 72, 25, FEZ_Components.FEZTouch.Color.Cyan);
                    lcd.DrawString(" Setting ", 20, BUTTON2_HEIGHT, FEZ_Components.FEZTouch.Color.Black, FEZ_Components.FEZTouch.Color.Cyan);
                }
            }
    
            static void lcd_TouchUpEvent(int x, int y)
            {
            }
    
            static void lcd_TouchDownEvent(int x, int y)
            {
                
            }
    
            static void lcd_TouchMoveEvent(int x, int y)
            {
                
            }
        }
    }

    hehe back then i created two thread, but due to this error i cut it to only one thread (sounds awkward). i really appreciate if somebody can check, what is really wrong with this script anyway.


    • Edited by e-free-thing Tuesday, March 6, 2012 8:25 AM reduce code
    Tuesday, March 6, 2012 8:22 AM
  • Hi e-free-thing,

      Thank you for sharing your code snippet for us. It seems that you use   yield return to solve your actual problem. We are very happy to see the results.

      Sincerely,

      Jason Wang


    Jason Wang [MSFT]
    MSDN Community Support | Feedback to us

    Friday, March 23, 2012 6:40 AM