C#不是只有实现了IEnumerable才能用LINQ

LINQ 是 C# 中常用的一种集成查询语言,允许你这样写代码:

from c in list where c.Id > 5 select c;

但是上述代码中的 list 的类型不一定非得实现 IEnumerable,事实上,只要有对应名字的扩展方法就可以了,比如有了叫做 Select 的方法就能用 select,有了叫做 Where 的方法就能用 where.

class Just<T> : Maybe<T>
{
    private readonly T value;
    public Just(T value) { this.value = value; }

    public override Maybe<U> Select<U>(Func<T, Maybe<U>> f) => f(value);
    public override string ToString() => $"Just {value}";
}

class Nothing<T> : Maybe<T>
{
    public override Maybe<U> Select<U>(Func<T, Maybe<U>> _) => new Nothing<U>();
    public override string ToString() => "Nothing";
}

abstract class Maybe<T>
{
    public abstract Maybe<U> Select<U>(Func<T, Maybe<U>> f);

    public Maybe<V> SelectMany<U, V>(Func<T, Maybe<U>> k, Func<T, U, V> s)
        => Select(x => k(x).Select(y => new Just<V>(s(x, y))));

    public Maybe<U> Where(Func<Maybe<T>, bool> f) => f(this) ? this : new Nothing<T>();
}

class Program
{
    public static void Main()
    {
        var x = new Just<int>(3);
        var y = new Just<int>(7);
        var z = new Nothing<int>();

        var u = from x0 in x from y0 in y select x0 + y0;
        var v = from x0 in x from z0 in z select x0 + z0;
        var just = from c in x where true select c;
        var nothing = from c in x where false select c;
    }
}