Tôi biết rất nhiều đã được viết về LINQ và hoạt động bên trong của nó. Lấy cảm hứng từ Jon Skeets EduLinq, tôi muốn làm sáng tỏ những gì đang diễn ra đằng sau các nhà khai thác LINQ. Vì vậy, những gì tôi đã cố gắng làm là để thực hiện Linqs Select() phương pháp mà âm thanh khá nhàm chán ngay từ cái nhìn đầu tiên. Nhưng những gì tôi thực sự cố gắng làm là triển khai nó mà không cần sử dụng từ khóa lợi nhuận.Triển khai LINQs Chọn không có từ khóa lợi nhuận. Không thể theo dõi luồng kiểm soát
Vì vậy, đây là những gì tôi có cho đến nay:
class Program
{
static void Main(string[] args)
{
var list = new int[] {1, 2, 3};
var otherList = list.MySelect(x => x.ToString()).MySelect(x => x + "test");
foreach (var item in otherList)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
}
public static class EnumerableEx
{
public static IEnumerable<R> MySelect<T, R>(this IEnumerable<T> sequence, Func<T, R> apply)
{
return new EnumerableWrapper<R, T>(sequence, apply);
}
}
public class EnumerableWrapper<T, O> : IEnumerable<T>
{
private readonly IEnumerable<O> _sequence;
private readonly Func<O, T> _apply;
public EnumerableWrapper(IEnumerable<O> sequence, Func<O, T> apply)
{
_sequence = sequence;
_apply = apply;
}
public IEnumerator<T> GetEnumerator()
{
return new EnumeratorWrapper<T, O>(_sequence, _apply);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class EnumeratorWrapper<T, O> : IEnumerator<T>
{
private readonly IEnumerator<O> _enumerator;
private readonly Func<O, T> _apply;
public EnumeratorWrapper(IEnumerable<O> sequence, Func<O, T> apply)
{
_enumerator = sequence.GetEnumerator();
_apply = apply;
}
public void Dispose()
{
}
public bool MoveNext()
{
var hasItems = _enumerator.MoveNext();
if (hasItems)
Current = _apply(_enumerator.Current);
return hasItems;
}
public void Reset()
{
_enumerator.Reset();
}
public T Current { get; private set; }
object IEnumerator.Current
{
get { return Current; }
}
}
Có vẻ như để làm việc. Tuy nhiên, tôi gặp khó khăn để theo dõi luồng điều khiển của nó. Như bạn có thể thấy, tôi chuỗi để chiếu. Điều này khiến cho những điều kỳ lạ (lạ đối với tôi!) Xảy ra trong phương thức MoveNext(). Nếu bạn thiết lập các điểm ngắt trong mỗi dòng của phương thức MoveNext(), bạn sẽ thấy rằng luồng điều khiển thực sự nhảy giữa các cá thể khác nhau và không bao giờ làm việc thông qua phương thức trong một lô. Nó nhảy như thể nó đang sử dụng các chủ đề khác nhau hoặc nếu chúng ta đang sử dụng năng suất. Nhưng cuối cùng, nó chỉ là một phương pháp bình thường vì vậy tôi tự hỏi những gì đang xảy ra ở đó?
AAAAAAAAAAARG !! Chắc chắn rồi! Tôi bị mù! Nhân tiện, việc trả lời nhanh của bạn bất cứ lúc nào khiến tôi nghĩ rằng bạn đã viết một bot rất thông minh để trả lời tất cả những điều thông minh đó ;-) – Christoph
@Christoph [Bài hát chủ đề X-Files] Chúng tôi chỉ có thể hy vọng rằng nó chỉ là "rất bot thông minh "... –