SlideShare a Scribd company logo
1 of 57
Rx .NET
Stas Rivkin
From inside out
@stas_rivkin
2
@stas_rivkin
Tasks
Not lazy
Not restartble
Feature description
Testable
3
Why Rx?
@stas_rivkin
Agenda
History
Build the Rx API – Observables inside-out
• All about the callbacks
• First building blocks
• Different Rx operators
Live demos
• Google search
• Drag and drop
“Cold” vs “Hot”
Summary & references
4
@stas_rivkin
About Me
More than 6 years of hands on with various technologies
• .NET stack (desktop mainly)
• Angular
• NodeJS
https://blog.oz-code.com/author/stasr
5
@stas_rivkin
Senior software consultant
interface IEnumerable<out T>
{
IEnumerator<T> GetEnumerator();
}
interface IObserver<in T>
{
void OnNext(T value);
void OnError(Exception error);
void OnCompleted();
}
interface IEnumerable<out T>
{
IEnumerator<T> GetEnumerator();
}
Eric Meijer
Push & Pull models
https://goo.gl/2wzXbe
PRO Tip – 36m:00
2009 – Rx released
Rx History
6
@stas_rivkin
interface IObservable<out T>
{
IDisposable Subscribe(IObserver<T> obs);
}
interface IEnumerator<out T>: IDisposable
{
bool MoveNext();
T Current { get; }
}
interface IEnumerator<out T>: IDisposable
{
bool MoveNext();
T Current { get; }
}
static void Main(string[] args)
{
Console.WriteLine("Before");
var list = new List<int>(new[] { 10, 20, 30, 40, 50, 60 });
list.ForEach(num => Console.WriteLine(num));
Console.WriteLine("After");
}
All About the Callbacks
7
@stas_rivkin
public class Program
{
static void Main(string[] args)
{
Button myBtn = new Button();
myBtn.Click += MyBtnOnClick;
}
private static void MyBtnOnClick(object sender, EventArgs eventArgs)
{
Console.WriteLine("Clicked");
}
}
public class Button
{
public event EventHandler Click;
public void RaiseClickEvent() => Click?.Invoke(this, EventArgs.Empty);
}
All About the Callbacks
8
@stas_rivkin
static async Task Main(string[] args) => await RunAsync(OnNext);
private static async Task RunAsync(
Action<string> onNext)
{
WebClient client = new WebClient();
onNext(await client.DownloadStringTaskAsync(“some-URL”));
}
private static void OnNext(string value) => Console.WriteLine(value);
All About the Callbacks
9
@stas_rivkin
static async Task Main(string[] args) => await RunAsync(OnNext, OnError)
private static async Task RunAsync(
Action<string> onNext,
Action<Exception> onError)
{
WebClient client = new WebClient();
try
{
onNext(await client.DownloadStringTaskAsync(“some-URL”));
}
catch (Exception e) { onError(e); }
}
private static void OnNext(string value) => Console.WriteLine(value);
private static void OnError(Exception e) => Console.WriteLine($":( {e}");
All About the Callbacks
10
@stas_rivkin
static async Task Main(string[] args) => await RunAsync(OnNext, OnError, OnCompleted);
private static async Task RunAsync(
Action<string> onNext,
Action<Exception> onError,
Action onCompleted)
{
WebClient client = new WebClient();
try
{
foreach (var id in new []{1,2,3})
{
onNext(await client.DownloadStringTaskAsync($“some-URL/{id}”));
}
onCompleted();
}
catch (Exception e) { onError(e); }
}
private static void OnNext(string value) => Console.WriteLine(value);
private static void OnError(Exception e) => Console.WriteLine($":( {e}");
private static void OnCompleted() => Console.WriteLine("Hooray!");
All About the Callbacks
11
@stas_rivkin
12
“Encapsulate
what varies”
Gang of four
@stas_rivkin
static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete);
public static void NeedData(
Action<int> onNext,
Action<Exception> onError,
Action onComplete)
{
foreach (var num in new[] { 10, 20, 30 })
{
onNext(num);
}
onComplete();
}
private static void OnNext(int value) => Console.WriteLine(value);
private static void OnError(Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(error);
Console.ResetColor();
}
private static void OnCompleted()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("done");
Console.ResetColor();
}
First Building Blocks
13
//...
@stas_rivkin
static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete);
public static void NeedData(
Action<int> onNext,
Action<Exception> onError,
Action onComplete)
{
foreach (var num in new[] { 10, 20, 30 })
{
onNext(num);
}
onComplete();
}
private static void OnNext(int value) => Console.WriteLine(value);
private static void OnError(Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(error);
Console.ResetColor();
}
private static void OnCompleted()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("done");
Console.ResetColor();
}
First Building Blocks
14
// ...
@stas_rivkin
static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete);
public static void NeedData(
Action<int> onNext,
Action<Exception> onError,
Action onComplete)
{
foreach (var num in new[] { 10, 20, 30 })
{
onNext(num);
}
onComplete();
}
private static void OnNext(int value) => Console.WriteLine(value);
private static void OnError(Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(error);
Console.ResetColor();
}
private static void OnCompleted()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("done");
Console.ResetColor();
}
First Building Blocks
15
// ...
@stas_rivkin
static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete);
public static void NeedData(
Action<int> onNext,
Action<Exception> onError,
Action onComplete)
{
foreach (var num in new[] { 10, 20, 30 })
{
onNext(num);
}
onComplete();
}
private static void OnNext(int value) => Console.WriteLine(value);
private static void OnError(Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(error);
Console.ResetColor();
}
private static void OnCompleted()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("done");
Console.ResetColor();
}
First Building Blocks
16
// ...
@stas_rivkin
static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete);
public static void NeedData(
Action<int> onNext,
Action<Exception> onError,
Action onComplete)
{
foreach (var num in new[] { 10, 20, 30 })
{
onNext(num);
}
onComplete();
}
private static void OnNext(int value) => Console.WriteLine(value);
private static void OnError(Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(error);
Console.ResetColor();
}
private static void OnCompleted()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("done");
Console.ResetColor();
}
First Building Blocks
17
@stas_rivkin
static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete);
public static void NeedData(
Action<int> onNext,
Action<Exception> onError,
Action onComplete)
{
foreach (var num in new[] { 10, 20, 30 })
{
onNext(num);
}
onComplete();
}
private static void OnNext(int value) => Console.WriteLine(value);
private static void OnError(Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(error);
Console.ResetColor();
}
private static void OnCompleted()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("done");
Console.ResetColor();
}
First Building Blocks
18
@stas_rivkin
static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete);
public static void NeedData(
Action<int> onNext,
Action<Exception> onError,
Action onComplete)
{
foreach (var num in new[] { 10, 20, 30 })
{
onNext(num);
}
onComplete();
}
private static void OnNext(int value) => Console.WriteLine(value);
private static void OnError(Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(error);
Console.ResetColor();
}
private static void OnCompleted()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("done");
Console.ResetColor();
}
First Building Blocks
19
@stas_rivkin
var data = NeedData ();
...
public IEnumerable<int> NeedData()
=> new[] { 10, 20, 30 };
static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete);
public static void NeedData(
Action<int> onNext,
Action<Exception> onError,
Action onComplete)
{
foreach (var num in new[] { 10, 20, 30 })
{
onNext(num);
}
onComplete();
}
private static void OnNext(int value) => Console.WriteLine(value);
private static void OnError(Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(error);
Console.ResetColor();
}
private static void OnCompleted()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("done");
Console.ResetColor();
}
First Building Blocks
20
@stas_rivkin
First Building Blocks
21
static void Main(string[] args)
{
var observer = new ConsoleObserver();
NeedData(observer);
}
public static void NeedData(ConsoleObserver observer)
{
foreach (var value in new[] { 10, 20, 30 })
{
observer.OnNext(value);
}
observer.OnCompleted();
}
public class ConsoleObserver
{
public void OnNext(int value)
{ ... }
public void OnError(Exception error)
{ ... }
public void OnCompleted()
{ ... }
}
public interface IObserver<in T>
{
void OnNext(T value);
void OnError(Exception error);
void OnCompleted();
}
@stas_rivkin
First Building Blocks
22
public interface IObserver<in T>
{
void OnNext(T value);
void OnError(Exception error);
void OnCompleted();
}
static void Main(string[] args)
{
var observer = new ConsoleObserver();
NeedData(observer);
}
public static void NeedData(IObserver<int> observer)
{
foreach (var value in new[] { 10, 20, 30 })
{
observer.OnNext(value);
}
observer.OnCompleted();
}
@stas_rivkin
First Building Blocks
23
public interface IObserver<in T>
{
void OnNext(T value);
void OnError(Exception error);
void OnCompleted();
}
static void Main(string[] args)
{
var observer = new ConsoleObserver();
Subscribe(observer);
}
public static void Subscribe(IObserver<int> observer)
{
foreach (var value in new[] { 10, 20, 30 })
{
observer.OnNext(value);
}
observer.OnCompleted();
}
@stas_rivkin
public class Observable : IObservable<int>
{
public void Subscribe(IObserver<int> observer)
{
foreach (var value in new[] { 10, 20, 30 })
{
observer.OnNext(value);
}
observer.OnCompleted();
}
}
public interface IObservable<out T>
{
void Subscribe(IObserver<T> observer);
}
First Building Blocks
24
static void Main(string[] args)
{
var observer = new ConsoleObserver();
var observable = new Observable();
observable.Subscribe(observer);
}
@stas_rivkin
First Building Blocks
25
public class Observable : IObservable<int>
{
public IDisposable Subscribe(IObserver<int> observer)
{
foreach (var value in new[] { 10, 20, 30 })
{
observer.OnNext(value);
}
observer.OnCompleted();
return Disposable.Empty;
}
}
public interface IObservable<out T>
{
IDisposable Subscribe(IObserver<T> observer);
}
@stas_rivkin
static void Main(string[] args)
{
var observer = new ConsoleObserver();
var observable = new Observable();
observable.Subscribe(observer);
}
First Building Blocks
26
static void Main(string[] args)
{
var observer = new ConsoleObserver();
var observable = new Observable(new[]{ 10, 20, 30 });
observable.Subscribe(observer);
}
public class Observable : IObservable<int>
{
private IEumerable<int> _values;
public Observable(IEumerable<int> values)
=> _values = values;
public IDisposable Subscribe(IObserver<int> observer)
{
foreach (var value in _values)
{
observer.OnNext(value);
}
observer.OnCompleted();
return Disposable.Empty;
}
}
@stas_rivkin
First Building Blocks
27
public class Observable<T> : IObservable<T>
{
private IEumerable<T> _values;
public Observable(IEumerable<T> values)
=> _values = values;
public IDisposable Subscribe(IObserver<T> observer)
{
foreach (var value in _values)
{
observer.OnNext(value);
}
observer.OnCompleted();
return Disposable.Empty;
}
}
@stas_rivkin
static void Main(string[] args)
{
var observer = new ConsoleObserver();
var observable = new Observable(new[]{ 10, 20, 30 });
observable.Subscribe(observer);
}
First Building Blocks
28
public class ToObservable<T> : IObservable<T>
{
private IEnumerable<T> _values;
public ToObservable(IEnumerable<T> values)
=> _values = values;
public IDisposable Subscribe(IObserver<T> observer)
{
foreach (var value in _values)
{
observer.OnNext(value);
}
observer.OnCompleted();
return Disposable.Empty;
}
}
static void Main(string[] args)
{
var observer = new ConsoleObserver();
var observable = new ToObservable(new[]{ 10, 20, 30 });
observable.Subscribe(observer);
}
@stas_rivkin
public static class ObservableExtensions
{
public static IObservable<T> ToObservable<T>
this IEnumerable<T> src)
=> new ToObservable<T>(src);
}
static void Main(string[] args)
{
var observer = new ConsoleObserver();
IObservable observable = new[]{ 10, 20, 30 }
.ToObservable();
observable.Subscribe(observer);
}
IEnumerable -> IObservable
29
@stas_rivkin
static void Main(string[] args)
{
var observer = new ConsoleObserver();
IObservable observable = new[]{ 10, 20, 30 }
.ToObservable();
observable.Subscribe(observer);
}
Where
30
@stas_rivkin
public static class ObservableExtensions
{
public static IObservable<T> ToObservable<T>
this IEnumerable<T> src)
=> new ToObservable<T>(src);
public static IObservable<T> Where<T>(
this IObservable<T> src,
Func<T, bool> filter)
=> new Where<T>(src, filter);
}
Where
31
@stas_rivkin
public static class ObservableExtensions
{
public static IObservable<T> ToObservable<T>
this IEnumerable<T> src)
=> new ToObservable<T>(src);
public static IObservable<T> Where<T>(
this IObservable<T> src,
Func<T, bool> filter)
=> new Where<T>(src, filter);
}
static void Main(string[] args)
{
var observer = new ConsoleObserver();
IObservable observable = new[]{ 10, 20, 30 }
.ToObservable()
.Where(n => n > 10);
observable.Subscribe(observer);
}
Where
32
public class Where<T> : IObservable<T>
{
private IObservable<T> _src;
private Func<T, bool> _filter;
public Where(
IObservable<T> src,
Func<T, bool> filter)
{
_src = src;
_filter = filter;
}
public IDisposable Subscribe(IObserver<T> observer)
{
//...
}
}
@stas_rivkin
Where
33
public class Where<T> : IObservable<T>,
{
private IObservable<T> _src;
private Func<T, bool> _filter;
private IObserver<T> _observer;
public Where(
IObservable<T> src,
Func<T, bool> filter)
{
_src = src;
_filter = filter;
}
public IDisposable Subscribe(IObserver<T> observer)
{
_observer = observer;
return new CompositeDisposable
{
_src.Subscribe(this),
Disposable.Create(() => _observer = null)
};
}
/* */
}
@stas_rivkin
IObserver<T>
Where
34
public class Where<T> : IObservable<T>, IObserver<T>
{
private IObservable<T> _src;
private Func<T, bool> _filter;
private IObserver<T> _observer;
public Where(
IObservable<T> src,
Func<T, bool> filter)
{
_src = src;
_filter = filter;
}
public IDisposable Subscribe(IObserver<T> observer)
{ ... }
public void OnNext(T value)
{
if(_filter(value)) _observer.OnNext(value);
}
public void OnError(Exception error) => _observer.OnError(error);
public void OnCompleted() => _observer.OnCompleted();
}
@stas_rivkin
static void Main(string[] args)
{
var observer = new ConsoleObserver();
IObservable observable = new[]{ 10, 20, 30 }
.ToObservable()
.Where(n => n > 10);
observable.Subscribe(observer);
}
Select
35
public static class ObservableExtensions
{
public static IObservable<T> ToObservable<T>
this IEnumerable<T> src)
=> new ToObservable<T>(src);
public static IObservable<T> Where<T>(
this IObservable<T> src,
Func<T,bool> filter)
=> new Where<T>(src, filter);
public static IObservable<TOut> Select<TIn, TOut>(
this IObservable<TIn> src,
Func<TIn, TOut> selector)
=> new Select<TIn, TOut>(src, selector);
}
@stas_rivkin
Select
36
static void Main(string[] args)
{
var observer = new ConsoleObserver();
IObservable observable = new[]{ 10, 20, 30 }
.ToObservable()
.Where(n => n > 10)
.Select(n => n * 10);
observable.Subscribe(observer);
}
@stas_rivkin
public static class ObservableExtensions
{
public static IObservable<T> ToObservable<T>
this IEnumerable<T> src)
=> new ToObservable<T>(src);
public static IObservable<T> Where<T>(
this IObservable<T> src,
Func<T,bool> filter)
=> new Where<T>(src, filter);
public static IObservable<TOut> Select<TIn, TOut>(
this IObservable<TIn> src,
Func<TIn, TOut> selector)
=> new Select<TIn, TOut>(src, selector);
}
public class Select<TIn, TOut> : IObservable<TOut>, IObserver<TIn>
{
private IObservable<TIn> _src;
private Func<TIn, TOut> _selector;
private IObserver<TOut> _observer;
public Select(
IObservable<TIn> src,
Func<TIn, TOut> selector)
{
_src = src;
_selector = selector;
}
public IDisposable Subscribe(IObserver<TOut> observer)
{ ... }
public void OnNext(TIn value)
{
_observer.OnNext(_selector(value));
}
public void OnError(Exception error) => _observer.OnError(error);
public void OnCompleted() => _observer.OnCompleted();
}
Select
37
@stas_rivkin

In Action
38
static void Main(string[] args)
{
var observer = new ConsoleObserver();
IDisposable subscription = new[]{ 10, 20, 30}
.ToObservable()
.Where(n => n > 10)
.Select(n => n * 10);
.Subscribe(observer);
}
Where(n => n > 10)
Select(n => n * 10)
@stas_rivkin
Filtering Projection Partitioning Joins Grouping Set
Element Generation Quantifiers Aggregation Error HandlingTime and
Concurrency
Where
OfType
Select
SelectMany
Materialize
Skip
Take
TakeUntil
CombineLatest
Concat
join
GroupBy
GroupByUntil
Buffer
Distinct
DistinctUntilChanged
Timeout
TimeInterval
ElementAt
First
Single
Range
Repeat
Defer
All
Any
Contains
Sum
Average
Scan
Catch
OnErrorResumeNext
Using
Rx Operators
@stas_rivkin
Timestamp
Rx Packages
40
@stas_rivkin
Google Search
1. At least 3 characters
2. Don’t send the same string again
41
@stas_rivkin
Demo
43
Where(newSearchToken => newSearchToken.Length > 2 )

@stas_rivkin
44
Where(newSearchToken => newSearchToken.Length > 2 )

Throttle(TimeSpan.FromSeconds(0.5))
0.2sec

@stas_rivkin
45
Where(newSearchToken => newSearchToken.Length > 2 )

Throttle(TimeSpan.FromSeconds(0.5))
DistinctUntilChanged()
0.2sec


@stas_rivkin
46
Select(searchToken => SearchService.SearchAsync(searchToken))
REA
REAC
Switch()
REA results are ignored since we
switched to the “REAC” results

@stas_rivkin
var dragObs = mouseMoveObs.SkipUntil(mouseDownObs).TakeUntil(mouseUpObs)
Drag and Drop
47
var mouseDownObs = Observable.FromEventPattern(UIElement, nameof(UIElement.MouseDown));
var mouseMoveObs = Observable.FromEventPattern(UIElement, nameof(UIElement.MouseMove));
var mouseUpObs = Observable.FromEventPattern(UIElement, nameof(UIElement.MouseUp));
.Repeat();
On each mouse-down on your target,
start processing mouse-moves for your target
until a single mouse-up on your target
On each mouse-down on your target,
start processing mouse-moves for your target
until a single mouse-up on your target
;
@stas_rivkin
Demo
49
Select(me => me.EventArgs.GetPosition(DrawingControl))
@stas_rivkin
50
Select(me => me.EventArgs.GetPosition(DrawingControl))
SelectMany(point => itemsStream.SelectMany((item,index) => …))itemsStream.SelectMany
@stas_rivkin
51
Observable.Return(new{item,Point = new Point(point.X+index, point.y)})
[0] [1] [2] [3] [4] [n]index:
point.X+index, point.y
@stas_rivkin
“Rx can make text fly”
52
Delay(TimeSpan.FromMilliseconds(index*75), loopScheduler)
Observable.Return(new{item,Point = new Point(point.X+index, point.y)})
[0] [1] [2] [3] [4] [n]index:
[1]*75ms
[2]*75ms
[n]*75ms
@stas_rivkin
“Rx can make text fly”
53
Select(me => me.EventArgs.GetPosition(DrawingControl))
SelectMany(point => itemsStream.SelectMany((item,index) => …))
@stas_rivkin
“Cold” vs “Hot”
54
Observables are “cold” by default
•“Cold” creates a new producer each time a consumer subscribes to it
•“Hot” observables share a single producer with every consumer that
subscribes to them
var aStream = Observable.Where(...).Select(...)
aStream.Subscribe(...); var shared = aStream.Publish().RefCount();
aStream.Subscribe(...);
aStream.Subscribe(...);
shared.Subscribe(...);
shared.Subscribe(...);
shared.Subscribe(...);
@stas_rivkin
Summary
Simple idea – definitely not some magic
Easy to compose between events, callbacks, time-based operations
• Treating events as collections
• Manipulating sets of events with “operators”
Observables are LAZY by nature
• “subscribe” to the Observable sometime in the future
• “dispose” from the observable to cancel & tear down the producer
55
@stas_rivkin
www.reactivex.io
github.com/Reactive-Extensions
www.manning.com/dresher
56
Resources
@stas_rivkin
Thanks for Coming
Q
A ?
@stas_rivkin
GitHub examples:
http://bit.ly/2whyHKt

More Related Content

What's hot

54602399 c-examples-51-to-108-programe-ee01083101
54602399 c-examples-51-to-108-programe-ee0108310154602399 c-examples-51-to-108-programe-ee01083101
54602399 c-examples-51-to-108-programe-ee01083101premrings
 
Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17LogeekNightUkraine
 
NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...
NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...
NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...DmitryChirkin1
 
ZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in ScalaZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in ScalaWiem Zine Elabidine
 
JavaScript 2016 for C# Developers
JavaScript 2016 for C# DevelopersJavaScript 2016 for C# Developers
JavaScript 2016 for C# DevelopersRick Beerendonk
 
The Ring programming language version 1.5.2 book - Part 74 of 181
The Ring programming language version 1.5.2 book - Part 74 of 181The Ring programming language version 1.5.2 book - Part 74 of 181
The Ring programming language version 1.5.2 book - Part 74 of 181Mahmoud Samir Fayed
 
What’s new in C# 6
What’s new in C# 6What’s new in C# 6
What’s new in C# 6Fiyaz Hasan
 
Student Data Base Using C/C++ Final Project
Student Data Base Using C/C++ Final ProjectStudent Data Base Using C/C++ Final Project
Student Data Base Using C/C++ Final ProjectHaqnawaz Ch
 
Меняем javascript с помощью javascript
Меняем javascript с помощью javascriptМеняем javascript с помощью javascript
Меняем javascript с помощью javascriptPavel Volokitin
 
ClojurianからみたElixir
ClojurianからみたElixirClojurianからみたElixir
ClojurianからみたElixirKent Ohashi
 
C# console programms
C# console programmsC# console programms
C# console programmsYasir Khan
 
Oops practical file
Oops practical fileOops practical file
Oops practical fileAnkit Dixit
 
CBSE Class XII Comp sc practical file
CBSE Class XII Comp sc practical fileCBSE Class XII Comp sc practical file
CBSE Class XII Comp sc practical filePranav Ghildiyal
 
The Ring programming language version 1.5.4 book - Part 77 of 185
The Ring programming language version 1.5.4 book - Part 77 of 185The Ring programming language version 1.5.4 book - Part 77 of 185
The Ring programming language version 1.5.4 book - Part 77 of 185Mahmoud Samir Fayed
 
Продвинутая отладка JavaScript с помощью Chrome Dev Tools
Продвинутая отладка JavaScript с помощью Chrome Dev ToolsПродвинутая отладка JavaScript с помощью Chrome Dev Tools
Продвинутая отладка JavaScript с помощью Chrome Dev ToolsFDConf
 

What's hot (20)

54602399 c-examples-51-to-108-programe-ee01083101
54602399 c-examples-51-to-108-programe-ee0108310154602399 c-examples-51-to-108-programe-ee01083101
54602399 c-examples-51-to-108-programe-ee01083101
 
Java Program
Java ProgramJava Program
Java Program
 
Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17
 
NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...
NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...
NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...
 
ZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in ScalaZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in Scala
 
JavaScript 2016 for C# Developers
JavaScript 2016 for C# DevelopersJavaScript 2016 for C# Developers
JavaScript 2016 for C# Developers
 
ZIO Queue
ZIO QueueZIO Queue
ZIO Queue
 
The Ring programming language version 1.5.2 book - Part 74 of 181
The Ring programming language version 1.5.2 book - Part 74 of 181The Ring programming language version 1.5.2 book - Part 74 of 181
The Ring programming language version 1.5.2 book - Part 74 of 181
 
What’s new in C# 6
What’s new in C# 6What’s new in C# 6
What’s new in C# 6
 
Student Data Base Using C/C++ Final Project
Student Data Base Using C/C++ Final ProjectStudent Data Base Using C/C++ Final Project
Student Data Base Using C/C++ Final Project
 
Меняем javascript с помощью javascript
Меняем javascript с помощью javascriptМеняем javascript с помощью javascript
Меняем javascript с помощью javascript
 
ClojurianからみたElixir
ClojurianからみたElixirClojurianからみたElixir
ClojurianからみたElixir
 
Cpp c++ 2
Cpp c++ 2Cpp c++ 2
Cpp c++ 2
 
C# console programms
C# console programmsC# console programms
C# console programms
 
Oops practical file
Oops practical fileOops practical file
Oops practical file
 
CBSE Class XII Comp sc practical file
CBSE Class XII Comp sc practical fileCBSE Class XII Comp sc practical file
CBSE Class XII Comp sc practical file
 
C sharp 8
C sharp 8C sharp 8
C sharp 8
 
The Ring programming language version 1.5.4 book - Part 77 of 185
The Ring programming language version 1.5.4 book - Part 77 of 185The Ring programming language version 1.5.4 book - Part 77 of 185
The Ring programming language version 1.5.4 book - Part 77 of 185
 
Berlin meetup
Berlin meetupBerlin meetup
Berlin meetup
 
Продвинутая отладка JavaScript с помощью Chrome Dev Tools
Продвинутая отладка JavaScript с помощью Chrome Dev ToolsПродвинутая отладка JavaScript с помощью Chrome Dev Tools
Продвинутая отладка JavaScript с помощью Chrome Dev Tools
 

Similar to Rx.NET, from the inside-out - Stas Rivkin - Codemotion Rome 2018

Дмитрий Верескун «Синтаксический сахар C#»
Дмитрий Верескун «Синтаксический сахар C#»Дмитрий Верескун «Синтаксический сахар C#»
Дмитрий Верескун «Синтаксический сахар C#»SpbDotNet Community
 
Effective C#
Effective C#Effective C#
Effective C#lantoli
 
Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0Oscar Renalias
 
C# 6 and 7 and Futures 20180607
C# 6 and 7 and Futures 20180607C# 6 and 7 and Futures 20180607
C# 6 and 7 and Futures 20180607Kevin Hazzard
 
NetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf EditionNetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf EditionPaulo Morgado
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaFrank Lyaruu
 
.NET Foundation, Future of .NET and C#
.NET Foundation, Future of .NET and C#.NET Foundation, Future of .NET and C#
.NET Foundation, Future of .NET and C#Bertrand Le Roy
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSAdam L Barrett
 
Is your C# optimized
Is your C# optimizedIs your C# optimized
Is your C# optimizedWoody Pewitt
 
Functional Principles for OO Developers
Functional Principles for OO DevelopersFunctional Principles for OO Developers
Functional Principles for OO Developersjessitron
 
Design Patterns - Compiler Case Study - Hands-on Examples
Design Patterns - Compiler Case Study - Hands-on ExamplesDesign Patterns - Compiler Case Study - Hands-on Examples
Design Patterns - Compiler Case Study - Hands-on ExamplesGanesh Samarthyam
 
RESTful API using scalaz (3)
RESTful API using scalaz (3)RESTful API using scalaz (3)
RESTful API using scalaz (3)Yeshwanth Kumar
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
Tamir Dresher - What’s new in ASP.NET Core 6
Tamir Dresher - What’s new in ASP.NET Core 6Tamir Dresher - What’s new in ASP.NET Core 6
Tamir Dresher - What’s new in ASP.NET Core 6Tamir Dresher
 

Similar to Rx.NET, from the inside-out - Stas Rivkin - Codemotion Rome 2018 (20)

Дмитрий Верескун «Синтаксический сахар C#»
Дмитрий Верескун «Синтаксический сахар C#»Дмитрий Верескун «Синтаксический сахар C#»
Дмитрий Верескун «Синтаксический сахар C#»
 
Effective C#
Effective C#Effective C#
Effective C#
 
Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0
 
C# 6 and 7 and Futures 20180607
C# 6 and 7 and Futures 20180607C# 6 and 7 and Futures 20180607
C# 6 and 7 and Futures 20180607
 
.net progrmming part2
.net progrmming part2.net progrmming part2
.net progrmming part2
 
NetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf EditionNetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf Edition
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJava
 
C# 7
C# 7C# 7
C# 7
 
.NET Foundation, Future of .NET and C#
.NET Foundation, Future of .NET and C#.NET Foundation, Future of .NET and C#
.NET Foundation, Future of .NET and C#
 
C++ practical
C++ practicalC++ practical
C++ practical
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
 
Is your C# optimized
Is your C# optimizedIs your C# optimized
Is your C# optimized
 
Functional Principles for OO Developers
Functional Principles for OO DevelopersFunctional Principles for OO Developers
Functional Principles for OO Developers
 
C# labprograms
C# labprogramsC# labprograms
C# labprograms
 
Design Patterns - Compiler Case Study - Hands-on Examples
Design Patterns - Compiler Case Study - Hands-on ExamplesDesign Patterns - Compiler Case Study - Hands-on Examples
Design Patterns - Compiler Case Study - Hands-on Examples
 
RESTful API using scalaz (3)
RESTful API using scalaz (3)RESTful API using scalaz (3)
RESTful API using scalaz (3)
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
greenDAO
greenDAOgreenDAO
greenDAO
 
Tamir Dresher - What’s new in ASP.NET Core 6
Tamir Dresher - What’s new in ASP.NET Core 6Tamir Dresher - What’s new in ASP.NET Core 6
Tamir Dresher - What’s new in ASP.NET Core 6
 
C# Today and Tomorrow
C# Today and TomorrowC# Today and Tomorrow
C# Today and Tomorrow
 

More from Codemotion

Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Codemotion
 
Pompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyPompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyCodemotion
 
Pastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaPastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaCodemotion
 
Pennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserPennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserCodemotion
 
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Codemotion
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Codemotion
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Codemotion
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 - Codemotion
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Codemotion
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Codemotion
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Codemotion
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Codemotion
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Codemotion
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Codemotion
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Codemotion
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...Codemotion
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Codemotion
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Codemotion
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Codemotion
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Codemotion
 

More from Codemotion (20)

Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
 
Pompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyPompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending story
 
Pastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaPastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storia
 
Pennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserPennisi - Essere Richard Altwasser
Pennisi - Essere Richard Altwasser
 
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
 

Recently uploaded

WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAndikSusilo4
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 

Recently uploaded (20)

WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & Application
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 

Rx.NET, from the inside-out - Stas Rivkin - Codemotion Rome 2018

  • 1. Rx .NET Stas Rivkin From inside out @stas_rivkin
  • 3. Tasks Not lazy Not restartble Feature description Testable 3 Why Rx? @stas_rivkin
  • 4. Agenda History Build the Rx API – Observables inside-out • All about the callbacks • First building blocks • Different Rx operators Live demos • Google search • Drag and drop “Cold” vs “Hot” Summary & references 4 @stas_rivkin
  • 5. About Me More than 6 years of hands on with various technologies • .NET stack (desktop mainly) • Angular • NodeJS https://blog.oz-code.com/author/stasr 5 @stas_rivkin Senior software consultant
  • 6. interface IEnumerable<out T> { IEnumerator<T> GetEnumerator(); } interface IObserver<in T> { void OnNext(T value); void OnError(Exception error); void OnCompleted(); } interface IEnumerable<out T> { IEnumerator<T> GetEnumerator(); } Eric Meijer Push & Pull models https://goo.gl/2wzXbe PRO Tip – 36m:00 2009 – Rx released Rx History 6 @stas_rivkin interface IObservable<out T> { IDisposable Subscribe(IObserver<T> obs); } interface IEnumerator<out T>: IDisposable { bool MoveNext(); T Current { get; } } interface IEnumerator<out T>: IDisposable { bool MoveNext(); T Current { get; } }
  • 7. static void Main(string[] args) { Console.WriteLine("Before"); var list = new List<int>(new[] { 10, 20, 30, 40, 50, 60 }); list.ForEach(num => Console.WriteLine(num)); Console.WriteLine("After"); } All About the Callbacks 7 @stas_rivkin
  • 8. public class Program { static void Main(string[] args) { Button myBtn = new Button(); myBtn.Click += MyBtnOnClick; } private static void MyBtnOnClick(object sender, EventArgs eventArgs) { Console.WriteLine("Clicked"); } } public class Button { public event EventHandler Click; public void RaiseClickEvent() => Click?.Invoke(this, EventArgs.Empty); } All About the Callbacks 8 @stas_rivkin
  • 9. static async Task Main(string[] args) => await RunAsync(OnNext); private static async Task RunAsync( Action<string> onNext) { WebClient client = new WebClient(); onNext(await client.DownloadStringTaskAsync(“some-URL”)); } private static void OnNext(string value) => Console.WriteLine(value); All About the Callbacks 9 @stas_rivkin
  • 10. static async Task Main(string[] args) => await RunAsync(OnNext, OnError) private static async Task RunAsync( Action<string> onNext, Action<Exception> onError) { WebClient client = new WebClient(); try { onNext(await client.DownloadStringTaskAsync(“some-URL”)); } catch (Exception e) { onError(e); } } private static void OnNext(string value) => Console.WriteLine(value); private static void OnError(Exception e) => Console.WriteLine($":( {e}"); All About the Callbacks 10 @stas_rivkin
  • 11. static async Task Main(string[] args) => await RunAsync(OnNext, OnError, OnCompleted); private static async Task RunAsync( Action<string> onNext, Action<Exception> onError, Action onCompleted) { WebClient client = new WebClient(); try { foreach (var id in new []{1,2,3}) { onNext(await client.DownloadStringTaskAsync($“some-URL/{id}”)); } onCompleted(); } catch (Exception e) { onError(e); } } private static void OnNext(string value) => Console.WriteLine(value); private static void OnError(Exception e) => Console.WriteLine($":( {e}"); private static void OnCompleted() => Console.WriteLine("Hooray!"); All About the Callbacks 11 @stas_rivkin
  • 13. static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete); public static void NeedData( Action<int> onNext, Action<Exception> onError, Action onComplete) { foreach (var num in new[] { 10, 20, 30 }) { onNext(num); } onComplete(); } private static void OnNext(int value) => Console.WriteLine(value); private static void OnError(Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(error); Console.ResetColor(); } private static void OnCompleted() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("done"); Console.ResetColor(); } First Building Blocks 13 //... @stas_rivkin
  • 14. static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete); public static void NeedData( Action<int> onNext, Action<Exception> onError, Action onComplete) { foreach (var num in new[] { 10, 20, 30 }) { onNext(num); } onComplete(); } private static void OnNext(int value) => Console.WriteLine(value); private static void OnError(Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(error); Console.ResetColor(); } private static void OnCompleted() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("done"); Console.ResetColor(); } First Building Blocks 14 // ... @stas_rivkin
  • 15. static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete); public static void NeedData( Action<int> onNext, Action<Exception> onError, Action onComplete) { foreach (var num in new[] { 10, 20, 30 }) { onNext(num); } onComplete(); } private static void OnNext(int value) => Console.WriteLine(value); private static void OnError(Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(error); Console.ResetColor(); } private static void OnCompleted() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("done"); Console.ResetColor(); } First Building Blocks 15 // ... @stas_rivkin
  • 16. static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete); public static void NeedData( Action<int> onNext, Action<Exception> onError, Action onComplete) { foreach (var num in new[] { 10, 20, 30 }) { onNext(num); } onComplete(); } private static void OnNext(int value) => Console.WriteLine(value); private static void OnError(Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(error); Console.ResetColor(); } private static void OnCompleted() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("done"); Console.ResetColor(); } First Building Blocks 16 // ... @stas_rivkin
  • 17. static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete); public static void NeedData( Action<int> onNext, Action<Exception> onError, Action onComplete) { foreach (var num in new[] { 10, 20, 30 }) { onNext(num); } onComplete(); } private static void OnNext(int value) => Console.WriteLine(value); private static void OnError(Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(error); Console.ResetColor(); } private static void OnCompleted() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("done"); Console.ResetColor(); } First Building Blocks 17 @stas_rivkin
  • 18. static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete); public static void NeedData( Action<int> onNext, Action<Exception> onError, Action onComplete) { foreach (var num in new[] { 10, 20, 30 }) { onNext(num); } onComplete(); } private static void OnNext(int value) => Console.WriteLine(value); private static void OnError(Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(error); Console.ResetColor(); } private static void OnCompleted() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("done"); Console.ResetColor(); } First Building Blocks 18 @stas_rivkin
  • 19. static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete); public static void NeedData( Action<int> onNext, Action<Exception> onError, Action onComplete) { foreach (var num in new[] { 10, 20, 30 }) { onNext(num); } onComplete(); } private static void OnNext(int value) => Console.WriteLine(value); private static void OnError(Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(error); Console.ResetColor(); } private static void OnCompleted() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("done"); Console.ResetColor(); } First Building Blocks 19 @stas_rivkin var data = NeedData (); ... public IEnumerable<int> NeedData() => new[] { 10, 20, 30 };
  • 20. static void Main(string[] args) => NeedData(OnNext, OnError, OnComplete); public static void NeedData( Action<int> onNext, Action<Exception> onError, Action onComplete) { foreach (var num in new[] { 10, 20, 30 }) { onNext(num); } onComplete(); } private static void OnNext(int value) => Console.WriteLine(value); private static void OnError(Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(error); Console.ResetColor(); } private static void OnCompleted() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("done"); Console.ResetColor(); } First Building Blocks 20 @stas_rivkin
  • 21. First Building Blocks 21 static void Main(string[] args) { var observer = new ConsoleObserver(); NeedData(observer); } public static void NeedData(ConsoleObserver observer) { foreach (var value in new[] { 10, 20, 30 }) { observer.OnNext(value); } observer.OnCompleted(); } public class ConsoleObserver { public void OnNext(int value) { ... } public void OnError(Exception error) { ... } public void OnCompleted() { ... } } public interface IObserver<in T> { void OnNext(T value); void OnError(Exception error); void OnCompleted(); } @stas_rivkin
  • 22. First Building Blocks 22 public interface IObserver<in T> { void OnNext(T value); void OnError(Exception error); void OnCompleted(); } static void Main(string[] args) { var observer = new ConsoleObserver(); NeedData(observer); } public static void NeedData(IObserver<int> observer) { foreach (var value in new[] { 10, 20, 30 }) { observer.OnNext(value); } observer.OnCompleted(); } @stas_rivkin
  • 23. First Building Blocks 23 public interface IObserver<in T> { void OnNext(T value); void OnError(Exception error); void OnCompleted(); } static void Main(string[] args) { var observer = new ConsoleObserver(); Subscribe(observer); } public static void Subscribe(IObserver<int> observer) { foreach (var value in new[] { 10, 20, 30 }) { observer.OnNext(value); } observer.OnCompleted(); } @stas_rivkin
  • 24. public class Observable : IObservable<int> { public void Subscribe(IObserver<int> observer) { foreach (var value in new[] { 10, 20, 30 }) { observer.OnNext(value); } observer.OnCompleted(); } } public interface IObservable<out T> { void Subscribe(IObserver<T> observer); } First Building Blocks 24 static void Main(string[] args) { var observer = new ConsoleObserver(); var observable = new Observable(); observable.Subscribe(observer); } @stas_rivkin
  • 25. First Building Blocks 25 public class Observable : IObservable<int> { public IDisposable Subscribe(IObserver<int> observer) { foreach (var value in new[] { 10, 20, 30 }) { observer.OnNext(value); } observer.OnCompleted(); return Disposable.Empty; } } public interface IObservable<out T> { IDisposable Subscribe(IObserver<T> observer); } @stas_rivkin static void Main(string[] args) { var observer = new ConsoleObserver(); var observable = new Observable(); observable.Subscribe(observer); }
  • 26. First Building Blocks 26 static void Main(string[] args) { var observer = new ConsoleObserver(); var observable = new Observable(new[]{ 10, 20, 30 }); observable.Subscribe(observer); } public class Observable : IObservable<int> { private IEumerable<int> _values; public Observable(IEumerable<int> values) => _values = values; public IDisposable Subscribe(IObserver<int> observer) { foreach (var value in _values) { observer.OnNext(value); } observer.OnCompleted(); return Disposable.Empty; } } @stas_rivkin
  • 27. First Building Blocks 27 public class Observable<T> : IObservable<T> { private IEumerable<T> _values; public Observable(IEumerable<T> values) => _values = values; public IDisposable Subscribe(IObserver<T> observer) { foreach (var value in _values) { observer.OnNext(value); } observer.OnCompleted(); return Disposable.Empty; } } @stas_rivkin static void Main(string[] args) { var observer = new ConsoleObserver(); var observable = new Observable(new[]{ 10, 20, 30 }); observable.Subscribe(observer); }
  • 28. First Building Blocks 28 public class ToObservable<T> : IObservable<T> { private IEnumerable<T> _values; public ToObservable(IEnumerable<T> values) => _values = values; public IDisposable Subscribe(IObserver<T> observer) { foreach (var value in _values) { observer.OnNext(value); } observer.OnCompleted(); return Disposable.Empty; } } static void Main(string[] args) { var observer = new ConsoleObserver(); var observable = new ToObservable(new[]{ 10, 20, 30 }); observable.Subscribe(observer); } @stas_rivkin
  • 29. public static class ObservableExtensions { public static IObservable<T> ToObservable<T> this IEnumerable<T> src) => new ToObservable<T>(src); } static void Main(string[] args) { var observer = new ConsoleObserver(); IObservable observable = new[]{ 10, 20, 30 } .ToObservable(); observable.Subscribe(observer); } IEnumerable -> IObservable 29 @stas_rivkin
  • 30. static void Main(string[] args) { var observer = new ConsoleObserver(); IObservable observable = new[]{ 10, 20, 30 } .ToObservable(); observable.Subscribe(observer); } Where 30 @stas_rivkin public static class ObservableExtensions { public static IObservable<T> ToObservable<T> this IEnumerable<T> src) => new ToObservable<T>(src); public static IObservable<T> Where<T>( this IObservable<T> src, Func<T, bool> filter) => new Where<T>(src, filter); }
  • 31. Where 31 @stas_rivkin public static class ObservableExtensions { public static IObservable<T> ToObservable<T> this IEnumerable<T> src) => new ToObservable<T>(src); public static IObservable<T> Where<T>( this IObservable<T> src, Func<T, bool> filter) => new Where<T>(src, filter); } static void Main(string[] args) { var observer = new ConsoleObserver(); IObservable observable = new[]{ 10, 20, 30 } .ToObservable() .Where(n => n > 10); observable.Subscribe(observer); }
  • 32. Where 32 public class Where<T> : IObservable<T> { private IObservable<T> _src; private Func<T, bool> _filter; public Where( IObservable<T> src, Func<T, bool> filter) { _src = src; _filter = filter; } public IDisposable Subscribe(IObserver<T> observer) { //... } } @stas_rivkin
  • 33. Where 33 public class Where<T> : IObservable<T>, { private IObservable<T> _src; private Func<T, bool> _filter; private IObserver<T> _observer; public Where( IObservable<T> src, Func<T, bool> filter) { _src = src; _filter = filter; } public IDisposable Subscribe(IObserver<T> observer) { _observer = observer; return new CompositeDisposable { _src.Subscribe(this), Disposable.Create(() => _observer = null) }; } /* */ } @stas_rivkin IObserver<T>
  • 34. Where 34 public class Where<T> : IObservable<T>, IObserver<T> { private IObservable<T> _src; private Func<T, bool> _filter; private IObserver<T> _observer; public Where( IObservable<T> src, Func<T, bool> filter) { _src = src; _filter = filter; } public IDisposable Subscribe(IObserver<T> observer) { ... } public void OnNext(T value) { if(_filter(value)) _observer.OnNext(value); } public void OnError(Exception error) => _observer.OnError(error); public void OnCompleted() => _observer.OnCompleted(); } @stas_rivkin
  • 35. static void Main(string[] args) { var observer = new ConsoleObserver(); IObservable observable = new[]{ 10, 20, 30 } .ToObservable() .Where(n => n > 10); observable.Subscribe(observer); } Select 35 public static class ObservableExtensions { public static IObservable<T> ToObservable<T> this IEnumerable<T> src) => new ToObservable<T>(src); public static IObservable<T> Where<T>( this IObservable<T> src, Func<T,bool> filter) => new Where<T>(src, filter); public static IObservable<TOut> Select<TIn, TOut>( this IObservable<TIn> src, Func<TIn, TOut> selector) => new Select<TIn, TOut>(src, selector); } @stas_rivkin
  • 36. Select 36 static void Main(string[] args) { var observer = new ConsoleObserver(); IObservable observable = new[]{ 10, 20, 30 } .ToObservable() .Where(n => n > 10) .Select(n => n * 10); observable.Subscribe(observer); } @stas_rivkin public static class ObservableExtensions { public static IObservable<T> ToObservable<T> this IEnumerable<T> src) => new ToObservable<T>(src); public static IObservable<T> Where<T>( this IObservable<T> src, Func<T,bool> filter) => new Where<T>(src, filter); public static IObservable<TOut> Select<TIn, TOut>( this IObservable<TIn> src, Func<TIn, TOut> selector) => new Select<TIn, TOut>(src, selector); }
  • 37. public class Select<TIn, TOut> : IObservable<TOut>, IObserver<TIn> { private IObservable<TIn> _src; private Func<TIn, TOut> _selector; private IObserver<TOut> _observer; public Select( IObservable<TIn> src, Func<TIn, TOut> selector) { _src = src; _selector = selector; } public IDisposable Subscribe(IObserver<TOut> observer) { ... } public void OnNext(TIn value) { _observer.OnNext(_selector(value)); } public void OnError(Exception error) => _observer.OnError(error); public void OnCompleted() => _observer.OnCompleted(); } Select 37 @stas_rivkin
  • 38.  In Action 38 static void Main(string[] args) { var observer = new ConsoleObserver(); IDisposable subscription = new[]{ 10, 20, 30} .ToObservable() .Where(n => n > 10) .Select(n => n * 10); .Subscribe(observer); } Where(n => n > 10) Select(n => n * 10) @stas_rivkin
  • 39. Filtering Projection Partitioning Joins Grouping Set Element Generation Quantifiers Aggregation Error HandlingTime and Concurrency Where OfType Select SelectMany Materialize Skip Take TakeUntil CombineLatest Concat join GroupBy GroupByUntil Buffer Distinct DistinctUntilChanged Timeout TimeInterval ElementAt First Single Range Repeat Defer All Any Contains Sum Average Scan Catch OnErrorResumeNext Using Rx Operators @stas_rivkin Timestamp
  • 41. Google Search 1. At least 3 characters 2. Don’t send the same string again 41 @stas_rivkin
  • 42. Demo
  • 44. 44 Where(newSearchToken => newSearchToken.Length > 2 )  Throttle(TimeSpan.FromSeconds(0.5)) 0.2sec  @stas_rivkin
  • 45. 45 Where(newSearchToken => newSearchToken.Length > 2 )  Throttle(TimeSpan.FromSeconds(0.5)) DistinctUntilChanged() 0.2sec   @stas_rivkin
  • 46. 46 Select(searchToken => SearchService.SearchAsync(searchToken)) REA REAC Switch() REA results are ignored since we switched to the “REAC” results  @stas_rivkin
  • 47. var dragObs = mouseMoveObs.SkipUntil(mouseDownObs).TakeUntil(mouseUpObs) Drag and Drop 47 var mouseDownObs = Observable.FromEventPattern(UIElement, nameof(UIElement.MouseDown)); var mouseMoveObs = Observable.FromEventPattern(UIElement, nameof(UIElement.MouseMove)); var mouseUpObs = Observable.FromEventPattern(UIElement, nameof(UIElement.MouseUp)); .Repeat(); On each mouse-down on your target, start processing mouse-moves for your target until a single mouse-up on your target On each mouse-down on your target, start processing mouse-moves for your target until a single mouse-up on your target ; @stas_rivkin
  • 48. Demo
  • 50. 50 Select(me => me.EventArgs.GetPosition(DrawingControl)) SelectMany(point => itemsStream.SelectMany((item,index) => …))itemsStream.SelectMany @stas_rivkin
  • 51. 51 Observable.Return(new{item,Point = new Point(point.X+index, point.y)}) [0] [1] [2] [3] [4] [n]index: point.X+index, point.y @stas_rivkin “Rx can make text fly”
  • 52. 52 Delay(TimeSpan.FromMilliseconds(index*75), loopScheduler) Observable.Return(new{item,Point = new Point(point.X+index, point.y)}) [0] [1] [2] [3] [4] [n]index: [1]*75ms [2]*75ms [n]*75ms @stas_rivkin “Rx can make text fly”
  • 53. 53 Select(me => me.EventArgs.GetPosition(DrawingControl)) SelectMany(point => itemsStream.SelectMany((item,index) => …)) @stas_rivkin
  • 54. “Cold” vs “Hot” 54 Observables are “cold” by default •“Cold” creates a new producer each time a consumer subscribes to it •“Hot” observables share a single producer with every consumer that subscribes to them var aStream = Observable.Where(...).Select(...) aStream.Subscribe(...); var shared = aStream.Publish().RefCount(); aStream.Subscribe(...); aStream.Subscribe(...); shared.Subscribe(...); shared.Subscribe(...); shared.Subscribe(...); @stas_rivkin
  • 55. Summary Simple idea – definitely not some magic Easy to compose between events, callbacks, time-based operations • Treating events as collections • Manipulating sets of events with “operators” Observables are LAZY by nature • “subscribe” to the Observable sometime in the future • “dispose” from the observable to cancel & tear down the producer 55 @stas_rivkin
  • 57. Thanks for Coming Q A ? @stas_rivkin GitHub examples: http://bit.ly/2whyHKt

Editor's Notes

  1. Don’t get me wrong! I love async-await… I think it made our async lives much more easier! But the problem with async-await is, it can’t be concise and the reason it can’t be concise is because await doesn’t help me get rid of state, immutable state. The enemy of any user-interface application. The more mutable state I have, the harder it makes me to figure out the state of my program. The other thing is, I want describe an idea, a feature - in a one readable place without going through some sort of a callback chain. Sooo thing that I’m excited about with Rx, is it allows you to write that kind of code, a lot more dependable, a lot more relible… async code I can write something.. a I’m pretty sure it is going to do what I what… Ohh… and it’s testable… I can write tests which run the same way every time…
  2. My name is Stas Rivkin **and you already figured out from my name, I do speak Russian. But this talk will be in English, cause frankly I have no clue how to pronounce software technicalities in Russian. I’m a software consultant @codevalue Israel. CodeValue is a consulating company and we are also the proud development center of OzCode the amazing debugging extensions for visual studio. Few of it’s key features is visualizing LINQ debugging and filtering collection in run-time. I have more than 5 years of hands on experience in .NET C#, mainly in client-side development. I’ve build applications from physics analytics to C&C geo-location based applications. I’m also a OzCode Evangelist and a blogger. You can check-out few blogs I’ve wrote on “How to mongoDB in C#” And that’s the end of my self promotion(it never hurts right?). So.. Let’s talk about reactive extensions… how many of you guys heard about reactive extensions?
  3. So want do we really want? We want to have one language which talks about all those three things.. Cause really events and callbacks… and a task returning from being completed are really all events, right? They all do the same thing. But we can’t refer to them at the same language. We need a func of something for the callback and a delegate of some sort for event, and we need to await something to be completed. I’m treating all of those unified things as a separate things and I can’t combine them. And when I can’t combine them easily.. I can’t describe how they relate.. Easily. ???So if I have a UI button that has a click event and I can’t describe how that click event is related to this async go and do google search?? Sooo… what if we try to make the most generic API which handles all of those scenarios in a unified language ?
  4. So… We have an Observer object which wants to observe something.. So this makes that object to an Observable… TA-Daaa..
  5. So… We have an Observer object which wants to observe something.. So this makes that object to an Observable… TA-Daaa..
  6. So… We have an Observer object which wants to observe something.. So this makes that object to an Observable… TA-Daaa..
  7. So… We have an Observer object which wants to observe something.. So this makes that object to an Observable… TA-Daaa..
  8. So… We have an Observer object which wants to observe something.. So this makes that object to an Observable… TA-Daaa..
  9. So… We have an Observer object which wants to observe something.. So this makes that object to an Observable… TA-Daaa..
  10. So… We have an Observer object which wants to observe something.. So this makes that object to an Observable… TA-Daaa..
  11. So… We have an Observer object which wants to observe something.. So this makes that object to an Observable… TA-Daaa..