2

I am able to deconstruct a container via an extension method:

var limits = new[] { MyEnum.A , MyEnum.B , MyEnum.C }
        .ToDictionary( x => x ,
                       x => ( SupportedLimit: GetLimit( x ) , RequiredLimit: 0 ) );

public static class Extensions
{
    public static void Deconstruct<TKey, TVal>(
        this KeyValuePair<TKey , TVal> tuple ,
        out TKey key , out TVal value )
    {
        key = tuple.Key;
        value = tuple.Value;
    }

    public static void Deconstruct<TKey, TVal1, TVal2>(
        this KeyValuePair<TKey , (TVal1,TVal2)> tuple ,
        out TKey key , out TVal1 v1 , out TVal2 v2 )
    {
        key = tuple.Key;
        (v1 , v2) = tuple.Value;
    }
}

// works
foreach( var ( enumVal , supportedLimit , requiredLimit ) in limits )
    Debugger.Break();

How do I deconstruct a container/dictionary containing a System.ValueTuple in LINQ?

// won't work, .Where() expects Func<T,bool> not Func<T1,T2,T3,bool>

var failedLimits = limits.Where( ( _ , sup , req ) => sup < req );

I just wanted to know how (and if) it is possible to deconstruct the ValueTuple in (any) LINQ method. I guess I have to add an extension method for every Linq-method (List-like) + overloads for dictionaries + each amount of values in the ValueTuple. How would it look like for the Where() in the example?

nonsensation
  • 3,627
  • 6
  • 28
  • 41
  • Well first you need to undersatnd that a `Dictionary` is an `IEnumerable>`. – juharr Sep 07 '18 at 13:33
  • And how `Where` extension method works. – SᴇM Sep 07 '18 at 13:35
  • No you don't need to add extentions method for every Linq method. Just use the named parameters of your value tuple. That's the whole point of why they exist. Deconstruction should only be needed when assigning the value tuple to multiple variables (typically on the return of a method). There's no need for it in a lambda expression, at least not that I can see. – juharr Sep 07 '18 at 13:40
  • Also make sure you're using value tuples in the right place. Other options are the reference Tuple, anonymous classes or just a plain old custom class. Each one has a preferred use case. Specifically value tuples are great for ridding code of out parameters, so maybe you should use them as the return type on your extension methods instead. – juharr Sep 07 '18 at 13:44
  • @juharr I find `limits.Where( ( _ , sup , req ) => sup < req );` more readable/terse than `limits.Where( kvp => kvp.Value.RequiredLimit < kvp.Value.SupportedLimit );` – nonsensation Sep 07 '18 at 13:47
  • @nonsensation Terse, yes. Readable, no. `SuppoertedLimit` is much or clear that `sup` in what it means. – juharr Sep 07 '18 at 13:49

2 Answers2

1
public static class LinqExtensions
{
    public static IEnumerable<KeyValuePair<TKey,(T1,T2)>> Where<TKey,T1,T2>(
        this IEnumerable<KeyValuePair<TKey,(T1,T2)>> source ,
        Func<TKey,T1,T2, Boolean> predicate )
        => source.Where( predicate );
}
  • Overloads for List-like types + every amount of ValueTuple-parameter
nonsensation
  • 3,627
  • 6
  • 28
  • 41
0

Since you're dealing with a Dictionary the values you iterate over are KeyValuePairs. You need to deal with the Value part of the KeyValuePair and then just use the named property of your value tuple.

var failedLimits = limits.Where(kvp => kvp.Value.SupportedLimit < req);
mjwills
  • 23,389
  • 6
  • 40
  • 63
juharr
  • 31,741
  • 4
  • 58
  • 93