【发布时间】:2016-07-21 08:28:58
【问题描述】:
在这个纯粹是为了练习而编造的例子中,这是我想要返回的内容:
如果两个学生在指定的时间段内加入学校,比如 2 秒,那么我想要一个数据结构返回这两个学生、他们加入的学校以及他们加入之间的时间间隔。
我一直在思考这些问题:
class Program
{
static void Main(string[] args)
{
ObserveStudentsJoiningWithin(TimeSpan.FromSeconds(2));
}
static void ObserveStudentsJoiningWithin(TimeSpan timeSpan)
{
var school = new School("School 1");
var admissionObservable =
Observable.FromEventPattern<StudentAdmittedEventArgs>(school, "StudentAdmitted");
var observable = admissionObservable.TimeInterval()
.Scan((current, next) =>
{
if (next.Interval - current.Interval <= timeSpan)
{
// But this won't work for me because
// this requires me to return a TSource
// and not a TResult
}
});
var subscription = observable.Subscribe(TimeIntervalValueHandler);
school.FillWithStudentsAsync(10, TimeSpan.FromSeconds(3));
school.FillWithStudentsAsync(8, TimeSpan.FromSeconds(1));
Console.WriteLine("Press any key to exit the program");
Console.ReadKey();
subscription.Dispose();
}
}
这是域:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SchoolManagementSystem
{
public class Student
{
private static int _studentNumber;
public Student(string name)
{
Name = name;
}
public string Name { get; set; }
public static Student CreateRandom()
{
var name = string.Format($"Student {++_studentNumber}");
return new Student(name);
}
public override string ToString()
{
return Name;
}
}
public class School: IEnumerable<Student>
{
private List<Student> _students;
public event StudentAdmitted StudentAdmitted;
public string Name { get; set; }
public School(string name)
{
Name = name;
_students = new List<Student>();
}
public void AdmitStudent(Student student)
{
if (!_students.Contains(student))
{
_students.Add(student);
OnStudentAdmitted(this, student);
}
}
protected virtual void OnStudentAdmitted(School school, Student student)
{
var args = new StudentAdmittedEventArgs(school, student);
StudentAdmitted?.Invoke(this, args);
}
public IEnumerator<Student> GetEnumerator()
{
return _students.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public delegate void StudentAdmitted(object sender, StudentAdmittedEventArgs args);
public class StudentAdmittedEventArgs : EventArgs
{
public StudentAdmittedEventArgs(School school, Student student): base()
{
School = school;
Student = student;
}
public School School { get; protected set; }
public Student Student { get; protected set; }
}
public static class Extensions
{
public async static void FillWithStudentsAsync(this School school, int howMany, TimeSpan gapBetweenEachAdmission)
{
if (school == null)
throw new ArgumentNullException("school");
if (howMany < 0)
throw new ArgumentOutOfRangeException("howMany");
if (howMany == 1)
{
school.AdmitStudent(Student.CreateRandom());
return;
}
for (int i = 0; i < howMany; i++)
{
await Task.Delay(gapBetweenEachAdmission);
school.AdmitStudent(Student.CreateRandom());
}
}
}
}
但是,Scan 运算符允许我只返回相同 TSource 的 observable。 Select 也不会在这里工作,因为我不能向前看(我可以用Scan 做的事情)并将当前项目与下一个项目一起投影,即使Select 允许我将TSource 转换为TResult。
我正在寻找介于两者之间的东西。
【问题讨论】:
-
Observable.Scan确实允许您返回累加器类型。 -
我的错。你说得对。如果你把它记下来作为答案?
标签: c# system.reactive