c# - 在 C# 中模拟 F# `with` 关键字

标签 c# f#

有没有办法在 C# 中模拟 F# 的 with 关键字?我知道它可能不会那么优雅,但我想知道是否有任何方法可以处理创建新的不可变数据结构副本。

F# 中的记录是 detailed here .

这是我尝试做的一个例子。我们将通过接口(interface)创建数据的“不可变” View ,同时在具体类中保持可变性。这让我们可以在本地(在工作时)发生变化,然后返回一个不可变的接口(interface)。这就是我们在 C# 中处理不变性的原因。

public interface IThing
{
    double A { get; }
    double B { get; }
}

public class Thing : IThing
{
    double A { get; set; }
    double B { get; set; }
}

但是,当需要对数据进行更改时,来回转换它的类型(或可变性!)并不是很安全,而且手动将类的每个属性转换为新实例。如果我们添加一个新的呢?我是否必须追踪每一次操纵?当我真的只需要我以前拥有的东西,但有[一些改变]时,我不想让 future 头疼。

例子:

// ...

IThing item = MethodThatDoesWork();

// Now I want to change it... how? This is ugly and error/change prone:
IThing changed = new Thing {
    A = item.A,
    B = 1.5
};

// ...

实现这一目标的合理策略是什么?你以前用过什么?

最佳答案

由于没有语法糖,我知道你必须:

  • 手工完成(见下文)
  • 使用一些反射/自动映射器(不喜欢这个)
  • 使用一些 AOP 技术(既不喜欢这些技术)

至少这是我现在能想到的。

我认为后两个不是一个好主意,因为你用大型机器来解决一个非常简单的问题。

是的,当你有成千上万的数据结构时,你可能会重新考虑这一点,但如果你只有几个,我就不会使用它。

所以剩下的基本上是智能构造函数和类似的东西 - 这是一个简单的例子,说明你如何做到这一点(注意你并不真的需要所有这些 - 挑选) - 它基本上是 错过使用null/nullable寻找你需要的东西 - 更好的选择可能是过载或类似 Option<T> 的东西数据类型,但现在我想你明白了:

class MyData
{
    private readonly int _intField;
    private readonly string _stringField;

    public MyData(int intField, string stringField)
    {
        _intField = intField;
        _stringField = stringField;
    }

    public MyData With(int? intValue = null, string stringValue = null)
    {
        return new MyData(
            intValue ?? _intField,
            stringValue ?? _stringField);
    }

    // should obviously be put into an extension-class of some sort
    public static MyData With(/*this*/ MyData from, int? intValue = null, string stringValue = null)
    {
        return from.With(intValue, stringValue);
    }

    public int IntField
    {
        get { return _intField; }
    }

    public string StringField
    {
        get { return _stringField; }
    }
}

关于c# - 在 C# 中模拟 F# `with` 关键字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32174274/

相关文章:

c# - 如何确定调用方法和类名?

c# - LINQ 查询数据表以检查记录是否存在

c# - 获取特定类中使用的类型

ubuntu - 如何为具有自动完成功能的 ubuntu 配置 Rider F#?

f# - 计算 F# 中元组列表的最小值和最大值

types - f# 将 obj 从 FSharpValue.MakeTuple 转换为元组类型

c# - EF - 调用 SaveChanges() 的类

c# - 不同机器上的 Guid 唯一性

.net - F# 的 timeit 函数

.net - 如何将标准输入管道与 fsharpi (fsi) 和单声道一起使用