c# - 在 C# 中实现响应式编程/函数

标签 c# reactive-programming

我最近在阅读有关游戏引擎设计的内容,最终偶然发现了这个:What is (functional) reactive programming?

我想知道如何准确地实现评分第二高的答案中给出的示例。在 C++ 中,将指针传递给存储鼠标坐标的值并返回该值而不是 int 就足够容易了。好吧,我们不能在 C# 中真正做到这一点,所以这是我们的第一个问题。我们是否需要调用一些“更新”函数来使所有值保持最新?

其次,如何处理语法?赋值很简单。但是做一些像“每次我要求它时都从中获取鼠标位置和分钟 14”这样的事情稍微更..复杂..

最后,我想知道当您直接引用 C# 中的任何对象时,如何使它返回一个值。例如

int test = 1;

test 会返回 1。所以我可以做类似 1 + test which = 2 的事情

但是如果我有一个实例

public class ReactiveInt {
     int myValue
}

在尝试将 int 相加时,我不能像上面那样做。

抱歉,我猜这个问题太笼统了。如果可以给出一个简单的示例来演示与该答案中讨论的功能相似的功能,我想我所有的问题都会得到解答..

最佳答案

问题

问题一

I can't just do what i did above when trying to add int's together.

其实这就是重点。在响应式编程中,您不想强制性地将两个数字相加,而是希望根据其他数字定义新数字。因此,c = a + b,这样的 c 总是等于 a + b,即使 >ab 更改:c 相对于 ab 是响应式(Reactive)的。

var a = new BehaviorSubject(3);
var b = new BehaviorSubject(1);
var c = Rx.Observable.combineLatest(a, b, function(vals) {
    return vals[0] + vals[1];
});

问题二

I was wondering how exactly one would implement the example given in the 2nd highest rated answer.

最简单的答案 haskell 中的列表和高阶函数。

你不想要的答案 函数响应式编程违背了你在命令式编程中学到的一切,你将不得不重新学习如何 如果你想做纯函数式响应式(Reactive)编程的话。如果不这样做,您将最终制作各种依赖性跟踪库,例如 KnockoutJS , 当你可以在几百行中用类似 RxJS-Splash 的东西做同样的事情时,如果您一开始使用 FRP。 (请注意 Splash 是如何基于 Rx 的,它是可重用的代码,而 Knockout 是纯粹的特定于实现的代码)。

FRP 有事件时间 的概念,而依赖跟踪只有变化 的概念.功能响应式代码与命令式代码一样存在。它不是“建立在命令式代码之上”。 (是的,它仍然可以编译成汇编……不是重点),它在概念上根本上不同。

例子

使用 Microsoft 的 JavaScript 响应式扩展 (RxJS)

请记住,Rx 现在支持多种语言,包括本地语言 C++ .

示例的直接端口

var moves = $(document).onAsObservable('mousemove')
    .map(function(e) {
        return {
            x: e.pageX,
            y: e.pageY
        };
    });

var xs = moves.map(function(move) { return move.x; });
var ys = moves.map(function(move) { return move.y; });

var minXs = xs.map(function(x) { return x - 16; });
var minYs = ys.map(function(y) { return y - 16; });
var maxYs = xs.map(function(x) { return x + 16; });
var maxYs = ys.map(function(y) { return y + 16; });

var boundingRect = Rx.Observable.combineLatest(minXs, minYs, maxXs, maxYs)
    .map(function(vals) {
        var minX = vals[0];
        var minY = vals[1];
        var maxX = vals[2];
        var maxY = vals[3];

        return new Rectangle(minX, minY, maxX, maxY);
    });

简化端口

由于矩形仅根据一个相关值(或事件)定义,因此您可以将其简化为以下内容:

var boundingRect = $(document).onAsObservable('mousemove')
    .map(function(e) {
        var x = e.pageX;
        var y = e.pageY;
        return new Rectangle(x - 16, y - 16, x + 16, y + 16);
        });

使用它

此时您可以使用它来组合其他可观察序列(随时间变化的值)。

var area = boundingRect.map(function(rect) {
    return rect.getSize();
    });

或直接订阅。

boundingRect.subscribe(function (rect) {
    // perform some action with the rect each time it changes.
    console.log(rect);
    });

但只有当它发生变化时才会这样!

如果我们希望在订阅后立即获得最新值,而不是必须等待矩形再次更改怎么办?嗯,这就是 BehaviorSubject 的用武之地。

var rects = new Rx.BehaviorSubject(new Rectangle(-1, -1, 1, 1));

rects.subscribe(function(rect) {
        // this would happen twice in this example.
        // Once for the initial value (above), and once when it is changed later (below).
        console.log(rect); 
    });

rects.onNext(new Rectangle(-1, -1, 1, 1));

但这不是原来的 observable,也不是很实用......

下面是如何使用一些内置功能将 Observable 更改为类似于 BehaviorSubject 的行为...

var rectsAndDefault = rects.startWith(new Rectangle()); // just give it an initial value
rectsAndDefault.subscribe(function(rect) {
    console.log(rect); // happens once for the "startWith" rectangle, and then again for all subsequent changes
    })

同样,FRP 是不同的。这是很好的不同,但这是一项艰巨的学习任务。当它开始让您大吃一惊时,您就会知道自己已经开始接受它。

关于c# - 在 C# 中实现响应式编程/函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9212554/

相关文章:

haskell - 在回合制 ascii 游戏中使用 FRP(尤其是响应式(Reactive)香蕉)是否有意义?

c# - 响应式(Reactive)编程中流之间的循环依赖

c# - 在 sqlConnections 上使用 'Using' 对性能有何影响

c# - 存储库模式 EF Core 更新方法

c# - C#如何从数据库读取数据并存储到数组

java - Akka : How to assign an Actor an alias path

java - react 堆项目 : downstream is slow

c# - 表单应用程序中的错误范围

c# - 如何在 If 语句中评估 Enum?

java - 将多个 Mono<List<Item>> 合并为一个