LINQ identity function?

后端 未结 7 2119
日久生厌
日久生厌 2020-12-03 16:22

Just a little niggle about LINQ syntax. I\'m flattening an IEnumerable> with SelectMany(x => x).

My problem i

相关标签:
7条回答
  • 2020-12-03 17:26

    Note: this answer was correct for C# 3, but at some point (C# 4? C# 5?) type inference improved so that the IdentityFunction method shown below can be used easily.


    No, there isn't. It would have to be generic, to start with:

    public static Func<T, T> IdentityFunction<T>()
    {
        return x => x;
    }
    

    But then type inference wouldn't work, so you'd have to do:

    SelectMany(Helpers.IdentityFunction<Foo>())
    

    which is a lot uglier than x => x.

    Another possibility is that you wrap this in an extension method:

    public static IEnumerable<T> Flatten<T>
        (this IEnumerable<IEnumerable<T>> source)
    {
        return source.SelectMany(x => x);
    }
    

    Unfortunately with generic variance the way it is, that may well fall foul of various cases in C# 3... it wouldn't be applicable to List<List<string>> for example. You could make it more generic:

    public static IEnumerable<TElement> Flatten<TElement, TWrapper>
        (this IEnumerable<TWrapper> source) where TWrapper : IEnumerable<TElement>
    {
        return source.SelectMany(x => x);
    }
    

    But again, you've then got type inference problems, I suspect...

    EDIT: To respond to the comments... yes, C# 4 makes this easier. Or rather, it makes the first Flatten method more useful than it is in C# 3. Here's an example which works in C# 4, but doesn't work in C# 3 because the compiler can't convert from List<List<string>> to IEnumerable<IEnumerable<string>>:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    public static class Extensions
    {
        public static IEnumerable<T> Flatten<T>
            (this IEnumerable<IEnumerable<T>> source)
        {
            return source.SelectMany(x => x);
        }
    }
    
    class Test
    {
        static void Main()
        {
            List<List<string>> strings = new List<List<string>>
            {
                new List<string> { "x", "y", "z" },
                new List<string> { "0", "1", "2" }
            };
    
            foreach (string x in strings.Flatten())
            {
                Console.WriteLine(x);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题