locked
Is this correct for returning multiple values of different data types from a function? RRS feed

  • Question

  • I need to return a string result and a bool value from a function, so I created an object[] return type.  It seems to work, but I am checking to see if this is the correct approach or if there is a better practice approach for doing something like this. 

    private void btnTestf_Click(object sender, EventArgs e)
    {
       object[] o1 = testMultiObjs();
       Console.WriteLine(o1[0].ToString());
       Console.WriteLine(o1[1].ToString());
    }

    private object[] testMultiObjs()
    {
       bool b1 = true;
       string s1 = "test";
       object[] o1 = new object[2];
       o1[0] = b1;
       o1[1] = s1;
       return o1;
    }

    Actually, in my original implementation of my function -- it was just supposed to return a bool value, but if something err'd out (in a try/catch block) -- I want now to return a bool (of false) and the err message.  Of course, if no err's then return the bool value and some happy message.

    Lastly, just a question -- in my function if I have a for loop that is checking for something and finds it and sets boolVal = true

    bool boolVal;
    for (int i = 0; i < o1.Length; i++)
    {
       ...
       if (boolVal == true)
          return boolVal;
    }

    ...

    boolVal = false;

    return boolVal;


    does the return statement in the for loop act like a break to break out of the function once boolVal == true?

    I am guessing yes.

    or would this function go all the way to the bottom and set boolVal = false if I don't break out the for loop after boolVal == true?


    Rich P


    • Edited by Rich P123 Friday, April 4, 2014 4:08 PM ......
    Friday, April 4, 2014 3:34 PM

Answers

  • If you have to return multiple values, this is what you can do:

    ref & out parameters. The only canonical example is TryParse(string, out int). And it is only a good idea because you can easily use the bool return value to check for parsing.

    Best would be to return a custom struct or class. If that would be too much write work, consider Tupel+Type Alias:

    using CustomReturn = Tupel<string, bool>;
    
    private CustomReturn testMultiObjs(){
      CustomReturn returnValue = new CustomReturn("test", true);
      return returnValue;
    }

    If the types are the same or the number is not know in advance, consider an array.

    Returning object[] or object in any scenario is highly discouraged
    Only ever use object if you really have too. Check if you can use generics when the types are not know when writing the class - they can solve most needs for object.


    Let's talk about MVVM: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/b1a8bf14-4acd-4d77-9df8-bdb95b02dbe2 Please mark post as helpfull and answers respectively.


    • Edited by Christopher84 Friday, April 4, 2014 4:14 PM
    • Marked as answer by Rich P123 Friday, April 4, 2014 4:34 PM
    Friday, April 4, 2014 4:12 PM
  • Actually, in my original implementation of my function -- it was just supposed to return a bool value, but if something err'd out (in a try/catch block) -- I want now to return a bool (of false) and the err message.  Of course, if no err's then return the bool value and some happy message.

    It might be that your function is doing too much or that you try to solve a too specific problem with a function. Not everthing can be made generic enough to warant a extra function in a function library.

    If you catch an exception you should either handle it (so the following code does not needs to know about it) or you let it bubble through. Exception.Message is only about 5% of the inforamtion of an exception. If you need to return the exception, just add a return type of Exception to the list but generally you should either completely process an Exception or let it completly through.

    Some other good practics for exception handling:

    http://www.codeproject.com/Articles/9538/Exception-Handling-Best-Practices-in-NET

    "Lastly, just a question -- in my function if I have a for loop that is checking for something and finds it and sets boolVal = true

    bool boolVal;
    for (int i = 0; i < o1.Length; i++)
    {
       ...
       if (boolVal == true)
          return boolVal;
    }

    ...

    boolVal = false;

    return boolVal;


    does the return statement in the for loop act like a break to break out of the function once boolVal == true?

    I am guessing yes."

    Yes, a return will end the function and break the loop. The only exception is that finally blocks (and cosntructs that work via finally, like "using" and "lock" - blocks) will be executed after them. Notet that you can omit the "== true" for bool variables. Every comparsion will be executed to a bool value anyway.
    Personalyl I prefer to just add the bool (that works as break condition for the loop) to the check at the beginning of the loop (continue while "!break && i<o.Lenght").


    Let's talk about MVVM: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/b1a8bf14-4acd-4d77-9df8-bdb95b02dbe2 Please mark post as helpfull and answers respectively.


    • Edited by Christopher84 Friday, April 4, 2014 4:25 PM
    • Marked as answer by Rich P123 Friday, April 4, 2014 4:34 PM
    Friday, April 4, 2014 4:23 PM
  •         public static T SomeMethod<T>() where T : IConvertible
            {
                var whateverObject = "whatever object";
                return (T)Convert.ChangeType(whateverObject, typeof(T), CultureInfo.InvariantCulture);   
            }

    This will allow you to return whatever object based on your logic in the method. The only stipulation is that you need to know ahead of time what you are expecting to get back from the function.

    SomeMethod<int>()

    Otherwise you can go with 

            public static object SomeMethod2()
            {
                var whatever = "blah";
                return whatever;
            }

    This just means you will be responsible for any kind of boxing and unboxing of your object.

    • Marked as answer by Rich P123 Friday, April 4, 2014 4:35 PM
    Friday, April 4, 2014 3:45 PM

All replies

  •         public static T SomeMethod<T>() where T : IConvertible
            {
                var whateverObject = "whatever object";
                return (T)Convert.ChangeType(whateverObject, typeof(T), CultureInfo.InvariantCulture);   
            }

    This will allow you to return whatever object based on your logic in the method. The only stipulation is that you need to know ahead of time what you are expecting to get back from the function.

    SomeMethod<int>()

    Otherwise you can go with 

            public static object SomeMethod2()
            {
                var whatever = "blah";
                return whatever;
            }

    This just means you will be responsible for any kind of boxing and unboxing of your object.

    • Marked as answer by Rich P123 Friday, April 4, 2014 4:35 PM
    Friday, April 4, 2014 3:45 PM
  • Thank you for this reply.  This is quite cool -- now I see that I can return a variety of data types.  This is actually a side result of my original question (which I just changed the title of the post -- I meant to ask about returning multiple values of different data types.

    Going back to the original question -- which I did not specify accurately enough -- I want to return multiple values of different data types.  I decided to go with an object[] array.  I'm sure there is something a little more sophisticated -- with Generics?  What would it look like for returning multiple values of different data types?


    Rich P


    • Edited by Rich P123 Friday, April 4, 2014 4:10 PM ....
    Friday, April 4, 2014 4:08 PM
  • If you have to return multiple values, this is what you can do:

    ref & out parameters. The only canonical example is TryParse(string, out int). And it is only a good idea because you can easily use the bool return value to check for parsing.

    Best would be to return a custom struct or class. If that would be too much write work, consider Tupel+Type Alias:

    using CustomReturn = Tupel<string, bool>;
    
    private CustomReturn testMultiObjs(){
      CustomReturn returnValue = new CustomReturn("test", true);
      return returnValue;
    }

    If the types are the same or the number is not know in advance, consider an array.

    Returning object[] or object in any scenario is highly discouraged
    Only ever use object if you really have too. Check if you can use generics when the types are not know when writing the class - they can solve most needs for object.


    Let's talk about MVVM: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/b1a8bf14-4acd-4d77-9df8-bdb95b02dbe2 Please mark post as helpfull and answers respectively.


    • Edited by Christopher84 Friday, April 4, 2014 4:14 PM
    • Marked as answer by Rich P123 Friday, April 4, 2014 4:34 PM
    Friday, April 4, 2014 4:12 PM
  • Actually, in my original implementation of my function -- it was just supposed to return a bool value, but if something err'd out (in a try/catch block) -- I want now to return a bool (of false) and the err message.  Of course, if no err's then return the bool value and some happy message.

    It might be that your function is doing too much or that you try to solve a too specific problem with a function. Not everthing can be made generic enough to warant a extra function in a function library.

    If you catch an exception you should either handle it (so the following code does not needs to know about it) or you let it bubble through. Exception.Message is only about 5% of the inforamtion of an exception. If you need to return the exception, just add a return type of Exception to the list but generally you should either completely process an Exception or let it completly through.

    Some other good practics for exception handling:

    http://www.codeproject.com/Articles/9538/Exception-Handling-Best-Practices-in-NET

    "Lastly, just a question -- in my function if I have a for loop that is checking for something and finds it and sets boolVal = true

    bool boolVal;
    for (int i = 0; i < o1.Length; i++)
    {
       ...
       if (boolVal == true)
          return boolVal;
    }

    ...

    boolVal = false;

    return boolVal;


    does the return statement in the for loop act like a break to break out of the function once boolVal == true?

    I am guessing yes."

    Yes, a return will end the function and break the loop. The only exception is that finally blocks (and cosntructs that work via finally, like "using" and "lock" - blocks) will be executed after them. Notet that you can omit the "== true" for bool variables. Every comparsion will be executed to a bool value anyway.
    Personalyl I prefer to just add the bool (that works as break condition for the loop) to the check at the beginning of the loop (continue while "!break && i<o.Lenght").


    Let's talk about MVVM: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/b1a8bf14-4acd-4d77-9df8-bdb95b02dbe2 Please mark post as helpfull and answers respectively.


    • Edited by Christopher84 Friday, April 4, 2014 4:25 PM
    • Marked as answer by Rich P123 Friday, April 4, 2014 4:34 PM
    Friday, April 4, 2014 4:23 PM
  • Without knowing exactly your needs I would highly discourage the use of an object array/list. As previously stated by Christopher84

    My suggestions would be to either create a class that meets your needs, or alternatively use tuples, or use reference variables.

    Tuples will have one limitation and that is you can only place 8 data types per tuple.

    Custom classes can be cumbersome at times.

    Reference variables can be an annoyance as well.

    Tuples and Reference types are both going to require that you need your data types you need ahead of time. With custom classes you can write with generics that should handle all your data types if you don’t know how many variables you will have.

    Just out of curiosity what are you trying to do? There may be other alternatives but I do not know what you are trying to accomplish.

    Friday, April 4, 2014 4:37 PM
  • Tuples will have one limitation and that is you can only place 8 data types per tuple.

    Note entirely true. The documentation notes that you can make a Tupel whose last Type is another Tupel. Whose last type is again another tupel....

    Admitedly a bit cumbersome to use (if not write in the first place), but when you hit 8 types you propably should use a real class anyway. It might end up saving writework and would give you cleare parameter names then "T1" and "T8.T1".

    Edit: Hit Propose as answer by accident when trying to edit and now it won't let me unpropose.


    Let's talk about MVVM: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/b1a8bf14-4acd-4d77-9df8-bdb95b02dbe2 Please mark post as helpfull and answers respectively.


    Friday, April 4, 2014 6:24 PM
  • @Christopher84

    I would really hope no one is nesting tuples but yes you are correct you can nest tuples. 

    Monday, April 7, 2014 3:00 PM
  • For this particular project I am returning data to Excel.  This is a .Net com/interop library project.  I have tried this notation arr[][], but com (Excel) did not support that.  I also tried returning a list<...> but com (Excel) does not support generics.  So I was kind of stuck with object[] .   com (Excel) seems to support this -- which is the route I ended up taking (but I do like the Tuple suggestion). 

    I'm hoping future versions of MS Office will support more .Net stuff.


    Rich P

    Monday, April 7, 2014 4:02 PM
  • The .COM interop is no longer developed. For all intents, .NET replaces .COM. However there is strong interoperabilty between .COM and .NET.
    Sounds like you have an interop issue, specifically with mapping the types. .COM might use char[] for string (as that is how C++ does strings).

    If you want to write to XLSX or other modern files, use the OpemXML SDK or a ZipArchive and a few XMLReaders (because Office-X files are just renamed .zip with a bunch of XML files inside).


    Let's talk about MVVM: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/b1a8bf14-4acd-4d77-9df8-bdb95b02dbe2 Please mark post as helpfull and answers respectively.

    Monday, April 7, 2014 5:17 PM