0

I traced group source code, and found group will new a GroupedEnumerable object. But when I tried below code it can't use is GroupedEnumerable to check.

    var orders = new[] {
        new {ID=1,Country="US",CreateDate=new DateTime(2021,01,01),PrdtID="P0020",Qty=100,Amount=100},
        new {ID=2,Country="US",CreateDate=new DateTime(2021,01,02),PrdtID="P0021",Qty=200,Amount=200},
        new {ID=3,Country="US",CreateDate=new DateTime(2021,02,03),PrdtID="P0022",Qty=300,Amount=300},
        new {ID=4,Country="US",CreateDate=new DateTime(2021,02,04),PrdtID="P0023",Qty=400,Amount=400},
        new {ID=5,Country="CN",CreateDate=new DateTime(2021,01,01),PrdtID="P0020",Qty=100,Amount=100},
        new {ID=6,Country="CN",CreateDate=new DateTime(2021,01,02),PrdtID="P0021",Qty=200,Amount=200},
        new {ID=7,Country="CN",CreateDate=new DateTime(2021,02,03),PrdtID="P0022",Qty=300,Amount=300},
        new {ID=8,Country="CN",CreateDate=new DateTime(2021,02,04),PrdtID="P0023",Qty=400,Amount=400},
    };

    
    var query = from order in orders
        group order by new { order.CreateDate.Year, order.CreateDate.Month } into g1
        from g2 in (
            from order in g1
            group order by order.Country
        )
        group g2 by g1.Key;
    ;
    
    var isGroup = query is System.Linq.GroupedEnumerable;

enter image description here

group source code:

public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
    return new GroupedEnumerable<TSource, TKey>(source, keySelector, null);
}

public interface IGrouping<out TKey, out TElement> : IEnumerable<TElement>, IEnumerable
{
    TKey Key
    {
        get;
    }
}

using System.Collections.Generic;

public GroupedEnumerable(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
    if (source == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
    }
    if (keySelector == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keySelector);
    }
    _source = source;
    _keySelector = keySelector;
    _comparer = comparer;
}

Why I want to do this

I want to make a helper, check if input object is group value then using specified logic to solve it.


Update:

I found GroupedEnumerable internal sealed class so it can't use is GroupedEnumerable to check

enter image description here

Wei Lin
  • 3,591
  • 2
  • 20
  • 52
  • Why do you want to do this? Surely you know it’s a group because you just a grouped it. Have you read https://stackoverflow.com/questions/503263/how-to-determine-if-a-type-implements-a-specific-generic-interface-type ? – Caius Jard May 31 '21 at 05:56
  • `System.Linq.GroupedEnumerable` instead of `System.Collections.GroupedEnumerable` ? – Cid May 31 '21 at 06:02
  • @Cid I found the problem is that GroupedEnumerable is internal sealed class – Wei Lin May 31 '21 at 06:04

3 Answers3

2

I believe you sould make your helper checking an interface, e.g. IEnumerable<IGrouping<TKey,TElement>>

I would suggest an extension on that interface

Sample:

static class Extension
{
    public static string AmI<TKey, TElement>(this IEnumerable<IGrouping<TKey, TElement>> source)
    {            
        Console.WriteLine(typeof(TKey));
        Console.WriteLine(typeof(TElement));
        return string.Join(',', source.Select(g => g.Key));
    }
}
ASpirin
  • 3,601
  • 1
  • 23
  • 32
1

Here is function and test

[TestMethod]
public void Test()
{
    var array = new int[] {1, 2, 3, 4, 5, 6};

    var grouping = array.GroupBy(x => x % 2);

    IsGrouping(grouping)
        .Should()
        .BeTrue();

    IsGrouping(array)
        .Should()
        .BeFalse();
}

private bool IsGrouping(IEnumerable someEnumerable)
{
    return someEnumerable
        .GetType()
        .GetInterfaces()
        .Any(x => x.IsGenericType
            && typeof(IEnumerable<>) == x.GetGenericTypeDefinition()
            && x.GenericTypeArguments.Length == 1 
            && x.GenericTypeArguments.First().IsGenericType
            && x.GenericTypeArguments.First().GetGenericTypeDefinition() == typeof(IGrouping<,>)
        );
}
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Kazys
  • 377
  • 2
  • 12
0

Now I use a bad way checking by name to solve problem.

    var isGroup = query.GetType().Name.StartsWith("GroupedEnumerable");
Wei Lin
  • 3,591
  • 2
  • 20
  • 52