February 20, 2013

Multiple return types? Tuple!


mathematical tuple
When coding there's one rule I don't want to break (It's my own rule btw):

Whenever a code block needs to be copied, it needs to be in a separate method.

Of course the disadvantage of this approach is that whenever you code a bug in this piece of code, it will surface wherever it's used in your application.

However, this (in my opinion) outweighs the frustration of fixing the same bug on multiple locations again and again and again and...


My problem.


In general, when using this 'generic' code, I settle for a single return value. A boolean result to indicate everything worked out fine (or not!) is enough. Sometimes I would like to have more return values then a single type. The most obvious options:
1 - Use a struct return value
2 - Use an object as return value
3 - Return a collection object (Dictionary, List, etc)
4 - Use ref parms...

Problem solved?


(1) requires a definition. Typically the return struct is specific to the function it returns. I need to define each struct or create something generic...
(2) as (1) : definitions : I'm a lazy programmer ;)
(3) when al return values are of the same type it's definitely an option, but when that's not the case...
(4) big function signature and the variables need to be declared 'upfront' even though they may remain 'empty'

Problem solved!


You can return a mixed type collection! It's not dynamic, so you cannot add elements on the fly like a 'usual' collection. Consider this (console example) code:

 using System;  
 using System.Collections.Generic;  
 using System.Linq;  
 using System.Text;  
 namespace ConsoleApplication1  
 {  
   class Program  
   {  
     static void Main(string[] args)  
     {  
       // the tuple for the result Item1: bool, Item2: String 
       Tuple<bool, String> result;  
       MyObject test = new MyObject();  

       result = test.TestMethod(new MyObject(true));  
       Console.WriteLine("test.TestMethod(new MyObject(true));");  
       Console.WriteLine(String.Format("succes:{0}\terr:{1}",result.Item1,result.Item2));  
       Console.ReadLine();  

       result = test.TestMethod(new MyObject(false));  
       Console.WriteLine("test.TestMethod(new MyObject(false));");  
       Console.WriteLine(String.Format("succes:{0}\terr:{1}",result.Item1,result.Item2));  
       Console.ReadLine();  
     }  
   }
  
   class MyObject  
   {  
     public bool BooleanProperty { get; set; }  
     public MyObject() : this(true) { }  
     public MyObject(bool succes)  
     {  
       BooleanProperty = succes;  
     }
  
     public Tuple<bool, String> TestMethod(MyObject obj)  
     {  
       bool succes = true;  
       String err = String.Empty;  
       try  
       {  
         if (!obj.BooleanProperty) throw new InvalidOperationException("Something went wrong!");  
       }  
       catch (Exception ex)  
       {  
         succes = false;  
         err = ex.Message;  
       }  
       return Tuple.Create<bool, String>(succes, err);  
     }  
   }  
 }  

You define the types in the Tuple declaration. Not just value types, any object can be added. You just need to keep the result Tuple 'in sync' with the expected return Tuple. The elements are stored in Item1, Item2, etc. Visual Studio intellisence shows the types of these items :)

Now we can return a 'mixed collection' 'on the fly' :)

No comments:

Post a Comment