When I have to write methods which return two values, I usually go about it as in the following code which returns a List<string>
. Or if I have to return e.g. a id and string, then I return a List<object>
and then pick them out with index number and recast the values.
This recasting and referencing by index seems inelegant so I want to develop a new habit for methods that return two values. What is the best pattern for this?
using System;
using System.Collections.Generic;
using System.Linq;
namespace MultipleReturns
{
class Program
{
static void Main(string[] args)
{
string extension = "txt";
{
List<string> entries = GetIdCodeAndFileName("first.txt", extension);
Console.WriteLine("{0}, {1}", entries[0], entries[1]);
}
{
List<string> entries = GetIdCodeAndFileName("first", extension);
Console.WriteLine("{0}, {1}", entries[0], entries[1]);
}
Console.ReadLine();
}
/// <summary>
/// gets "first.txt", "txt" and returns "first", "first.txt"
/// gets "first", "txt" and returns "first", "first.txt"
/// it is assumed that extensions will always match
/// </summary>
/// <param name="line"></param>
public static List<string> GetIdCodeAndFileName(string line, string extension)
{
if (line.Contains("."))
{
List<string> parts = line.BreakIntoParts(".");
List<string> returnItems = new List<string>();
returnItems.Add(parts[0]);
returnItems.Add(line);
return returnItems;
}
else
{
List<string> returnItems = new List<string>();
returnItems.Add(line);
returnItems.Add(line + "." + extension);
return returnItems;
}
}
}
public static class StringHelpers
{
public static List<string> BreakIntoParts(this string line, string separator)
{
if (String.IsNullOrEmpty(line))
return null;
else
{
return line.Split(new string[] { separator }, StringSplitOptions.None).Select(p => p.Trim()).ToList();
}
}
}
}
Ok, thanks everyone, I like the "return a custom class" answers best, never really thought out
was that easy to read, seems like a hack to me returning the first variable one way and the second another, here is my refactoring returning a custom class:
using System;
using System.Collections.Generic;
using System.Linq;
namespace MultipleReturns
{
class Program
{
static void Main(string[] args)
{
string extension = "txt";
{
IdCodeFileNamePair pair = GetIdCodeAndFileName("first.txt", extension);
Console.WriteLine("{0}, {1}", pair.IdCode, pair.FileName);
}
{
IdCodeFileNamePair pair = GetIdCodeAndFileName("first", extension);
Console.WriteLine("{0}, {1}", pair.IdCode, pair.FileName);
}
Console.ReadLine();
}
/// <summary>
/// gets "first.txt", "txt" and returns "first", "first.txt"
/// gets "first", "txt" and returns "first", "first.txt"
/// it is assumed that extensions will always match
/// </summary>
/// <param name="line"></param>
public static IdCodeFileNamePair GetIdCodeAndFileName(string line, string extension)
{
if (line.Contains("."))
{
List<string> parts = line.BreakIntoParts(".");
List<string> returnItems = new List<string>();
return new IdCodeFileNamePair { IdCode = parts[0], FileName = line };
}
else
{
List<string> returnItems = new List<string>();
return new IdCodeFileNamePair { IdCode = line, FileName = line + "." + extension };
}
}
}
public static class StringHelpers
{
public static List<string> BreakIntoParts(this string line, string separator)
{
if (String.IsNullOrEmpty(line))
return null;
else
{
return line.Split(new string[] { separator }, StringSplitOptions.None).Select(p => p.Trim()).ToList();
}
}
}
public class IdCodeFileNamePair
{
public string IdCode { get; set; }
public string FileName { get; set; }
}
}
I prefer either to create a lightweight class with two properties (see below), or to use a tuple (now available baked into the framework in .NET 4 but not hard to write your own)
class MyReturnValue
{
public string Id { get; set; }
public string Name { get; set; }
}
You could return a tuple, starting with 4.0.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With