How to return named tuples in C#?

32,137

Solution 1

Like this:

public (DateTime Start, DateTime End) DateRanges
{
    get
    {
        return (DateTime.MinValue, DateTime.MaxValue);
    }
}

Note: This requires a recent version of C# and .Net.

Incidentally, watch out for this usage pattern:

var from = filter?.DateRanges.Start;
var to = filter?.DateRanges.End;

That's inefficient because it causes two identical tuples to be created.

This is better:

var range = filter?.DateRanges;

if (range.HasValue)
{
    var from  = range.Value.Start;
    var to    = range.Value.End;
}

However note that tuples cannot be null (they are value types) so you could write it like so:

if (filter != null)
{
    var range = filter.DateRanges;
    var from  = range.Start;
    var to    = range.End;
    ...
}

Solution 2

class Program
{
    static void Main(string[] args)
    {
        test t = new test();
        Console.WriteLine(t.NamedTuple.start);
        Console.WriteLine(t.NamedTuple.stop);
        Console.Read();
    }
}

class test
{
    DateTime From;
    DateTime To;

    public (DateTime start, DateTime stop) NamedTuple
    {
        get
        {
            From = DateTime.Now.AddDays(-1).Date.AddMonths(-1);
            To = DateTime.Now.AddDays(-1).Date;
            return (From, To);
        }

    }
}
Share:
32,137
Karim Ali
Author by

Karim Ali

Updated on August 04, 2020

Comments

  • Karim Ali
    Karim Ali almost 4 years

    I have a property that returns two items of type DateTime. When returning these values I have to reference them as Item1 and Item2. How do I return with custom names e.g.

    filter?.DateRanges.From
    filter?.DateRanges.To
    

     

    public Tuple<DateTime, DateTime> DateRanges
    {
        get
        {
            From = DateTime.Now.AddDays(-1).Date.AddMonths(-1);
            To = DateTime.Now.AddDays(-1).Date;
    
            if (Preset != 0)
            {
                if (Preset == DatePreset.SpecificRange)
                {
                    From = From.Date;
                    To = To.Date;
                }
                else
                {
                    var dateRange = DateTime.Today.AddDays(-1).GetDateRangeByPreset(Preset);
                    From = dateRange.From;
                    To = dateRange.To;
                }
            }
    
            return new Tuple<DateTime, DateTime>(From, To);
        }
    

    usage:

    var from = filter?.DateRanges.Item1;
    var to = filter?.DateRanges.Item2;
    
    • JasperMoneyshot
      JasperMoneyshot almost 6 years
    • Rui Jarimba
      Rui Jarimba almost 6 years
      AFAIK there is no such thing as "named tuples". The alternative is to create a custom class with the property names you want
    • Jon Skeet
      Jon Skeet almost 6 years
      @RuiJarimba: There are definitely C# tuples with named elements, as of C# 7. They use ValueTuple<> rather than Tuple<> though.
    • Rui Jarimba
      Rui Jarimba almost 6 years
      Oh that's nice, I wasn't aware of that new feature. Thanks @DaisyShipton
  • Karim Ali
    Karim Ali almost 6 years
    strangely your second method does not work, var range = filter?.DateRanges; range variable doesn't allow Start and End
  • Matthew Watson
    Matthew Watson almost 6 years
    @KarimAli Ah, that's because it's a nullable (with the ?) so I should have been using .Value. I've edited my answer. But actually it's pointless using a nullable here because tuples CANNOT be null.
  • John Stock
    John Stock over 4 years
    This is not what was asked. Your answer is more than a syntax difference, it's a valuetype not reference which the Tuple<> syntax.
  • Matthew Watson
    Matthew Watson over 4 years
    @JohnStock I pointed out that it's a value type in my answer where I said (they are value types), so the fact that they are value types should be a surprise to no-one. I even bolded the part where I said tuples cannot be null.
  • Dave Black
    Dave Black almost 4 years
    @MatthewWatson I appreciate you pointing out how the code can be misused (made less efficient) by calling the DateRanges method twice thereby creating 2 tuples. And furthermore providing a better "usage" recommendation. While the fact you are creating 2 tuples is somewhat obvious by inspection, it can be easily missed - especially when you are using code written by someone else!