Welcome to mirror list, hosted at ThFree Co, Russian Federation.

EnumerableEx.Creation.cs « System.Interactive « NET « Ix - github.com/mono/rx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 2ba4f163b92411e23a4770dede879a51b46b63eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;

namespace System.Linq
{
    public static partial class EnumerableEx
    {
        /// <summary>
        /// Creates an enumerable sequence based on an enumerator factory function.
        /// </summary>
        /// <typeparam name="TResult">Result sequence element type.</typeparam>
        /// <param name="getEnumerator">Enumerator factory function.</param>
        /// <returns>Sequence that will invoke the enumerator factory upon a call to GetEnumerator.</returns>
        public static IEnumerable<TResult> Create<TResult>(Func<IEnumerator<TResult>> getEnumerator)
        {
            if (getEnumerator == null)
                throw new ArgumentNullException("getEnumerator");

            return new AnonymousEnumerable<TResult>(getEnumerator);
        }

        class AnonymousEnumerable<TResult> : IEnumerable<TResult>
        {
            private readonly Func<IEnumerator<TResult>> _getEnumerator;

            public AnonymousEnumerable(Func<IEnumerator<TResult>> getEnumerator)
            {
                _getEnumerator = getEnumerator;
            }

            public IEnumerator<TResult> GetEnumerator()
            {
                return _getEnumerator();
            }

            Collections.IEnumerator Collections.IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }

        /// <summary>
        /// Returns a sequence with a single element.
        /// </summary>
        /// <typeparam name="TResult">Result sequence element type.</typeparam>
        /// <param name="value">Single element of the resulting sequence.</param>
        /// <returns>Sequence with a single element.</returns>
        public static IEnumerable<TResult> Return<TResult>(TResult value)
        {
            yield return value;
        }

        /// <summary>
        /// Returns a sequence that throws an exception upon enumeration.
        /// </summary>
        /// <typeparam name="TResult">Result sequence element type.</typeparam>
        /// <param name="exception">Exception to throw upon enumerating the resulting sequence.</param>
        /// <returns>Sequence that throws the specified exception upon enumeration.</returns>
        public static IEnumerable<TResult> Throw<TResult>(Exception exception)
        {
            if (exception == null)
                throw new ArgumentNullException("exception");

            return Throw_<TResult>(exception);
        }

        private static IEnumerable<TResult> Throw_<TResult>(Exception exception)
        {
            throw exception;
#pragma warning disable 0162
            yield break;
#pragma warning restore 0162
        }

        /// <summary>
        /// Creates an enumerable sequence based on an enumerable factory function.
        /// </summary>
        /// <typeparam name="TResult">Result sequence element type.</typeparam>
        /// <param name="enumerableFactory">Enumerable factory function.</param>
        /// <returns>Sequence that will invoke the enumerable factory upon a call to GetEnumerator.</returns>
        public static IEnumerable<TResult> Defer<TResult>(Func<IEnumerable<TResult>> enumerableFactory)
        {
            if (enumerableFactory == null)
                throw new ArgumentNullException("enumerableFactory");

            return Defer_(enumerableFactory);
        }

        private static IEnumerable<TSource> Defer_<TSource>(Func<IEnumerable<TSource>> enumerableFactory)
        {
            foreach (var item in enumerableFactory())
                yield return item;
        }

        /// <summary>
        /// Generates a sequence by mimicking a for loop.
        /// </summary>
        /// <typeparam name="TState">State type.</typeparam>
        /// <typeparam name="TResult">Result sequence element type.</typeparam>
        /// <param name="initialState">Initial state of the generator loop.</param>
        /// <param name="condition">Loop condition.</param>
        /// <param name="iterate">State update function to run after every iteration of the generator loop.</param>
        /// <param name="resultSelector">Result selector to compute resulting sequence elements.</param>
        /// <returns>Sequence obtained by running the generator loop, yielding computed elements.</returns>
        public static IEnumerable<TResult> Generate<TState, TResult>(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector)
        {
            if (condition == null)
                throw new ArgumentNullException("condition");
            if (iterate == null)
                throw new ArgumentNullException("iterate");
            if (resultSelector == null)
                throw new ArgumentNullException("resultSelector");

            return Generate_(initialState, condition, iterate, resultSelector);
        }

        private static IEnumerable<TResult> Generate_<TState, TResult>(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector)
        {
            for (var i = initialState; condition(i); i = iterate(i))
                yield return resultSelector(i);
        }

        /// <summary>
        /// Generates a sequence that's dependent on a resource object whose lifetime is determined by the sequence usage duration.
        /// </summary>
        /// <typeparam name="TSource">Source element type.</typeparam>
        /// <typeparam name="TResource">Resource type.</typeparam>
        /// <param name="resourceFactory">Resource factory function.</param>
        /// <param name="enumerableFactory">Enumerable factory function, having access to the obtained resource.</param>
        /// <returns>Sequence whose use controls the lifetime of the associated obtained resource.</returns>
        public static IEnumerable<TSource> Using<TSource, TResource>(Func<TResource> resourceFactory, Func<TResource, IEnumerable<TSource>> enumerableFactory) where TResource : IDisposable
        {
            if (resourceFactory == null)
                throw new ArgumentNullException("resourceFactory");
            if (enumerableFactory == null)
                throw new ArgumentNullException("enumerableFactory");

            return Using_(resourceFactory, enumerableFactory);
        }

        private static IEnumerable<TSource> Using_<TSource, TResource>(Func<TResource> resourceFactory, Func<TResource, IEnumerable<TSource>> enumerableFactory) where TResource : IDisposable
        {
            using (var res = resourceFactory())
                foreach (var item in enumerableFactory(res))
                    yield return item;
        }

        /// <summary>
        /// Generates a sequence by repeating the given value infinitely.
        /// </summary>
        /// <typeparam name="TResult">Result sequence element type.</typeparam>
        /// <param name="value">Value to repreat in the resulting sequence.</param>
        /// <returns>Sequence repeating the given value infinitely.</returns>
        public static IEnumerable<TResult> Repeat<TResult>(TResult value)
        {
            while (true)
                yield return value;
        }

        /// <summary>
        /// Generates a sequence that contains one repeated value.
        /// </summary>
        /// <typeparam name="TResult">Result sequence element type.</typeparam>
        /// <param name="element">The value to be repeated.</param>
        /// <param name="count">The number of times to repeat the value in the generated sequence.</param>
        /// <returns>Sequence that contains a repeated value.</returns>
        public static IEnumerable<TResult> Repeat<TResult>(TResult element, int count)
        {
            return Enumerable.Repeat<TResult>(element, count);
        }
    }
}