可以使用Lambda /块初始化来简化此操作吗?

时间:2018-08-01 19:17:14

标签: c# initialization expression member-initialization

在Swift和C#之间来回跳动之前,我不确定是要忘记某些事情,还是C#不能轻易支持我所追求的目标。

考虑以下代码,该代码可计算Foo的初始值:

// Note: This is a field on an object, not a local variable.
int Foo = CalculateInitialFoo();

static int CalculateInitialFoo() {
    int x = 0;
    // Perform calculations to get x
    return x;
}

有什么方法可以执行这样的事情而无需创建单独的一次性使用功能,而是使用立即执行的lambda / block /任何内容?

在Swift中,这很简单。您可以使用立即执行的闭合符(花括号)(闭合括号和闭合括号),如下所示:

int Foo = {
    int x = 0
    // Perform calculations to get x
    return x
}()

清晰,简洁,并且不会使用仅用于初始化字段的功能使对象的界面混乱。

注意:为清楚起见,我要计算的属性。我正在尝试初始化一个成员字段,该成员字段需要多个语句才能完全完成。

3 个答案:

答案 0 :(得分:1)

我不建议这样做,但是您可以使用匿名函数进行初始化

int _foo = new Func<int>(() =>
{
    return 5;
})();

您是否有理由使用lambda而不是命名函数或作为计算属性来这样做?

我假设您想避免计算属性,因为您想要稍后修改该值,或者计算成本很高,并且想要缓存该值。

int? _fooBacking = null;

int Foo
{
    get
    {
        if (!_fooBacking.HasValue)
        {
            _fooBacking = 5;
        }

        return _fooBacking.Value;
    }
    set
    {
        _fooBacking = value;
    }
}

这将使用您在第一次获得条件时的评估结果,同时仍然允许分配值。

如果删除设置器,它将把它转换为缓存的计算。但是,使用此模式时要小心。财产获取者的副作用将不被接受,因为它们使代码难以遵循。

答案 1 :(得分:0)

要解决一般情况下的问题,您需要创建然后执行一个匿名函数,从技术上讲,您可以将其作为表达式来实现:

int Foo = new Func<int>(() => 
    {
        int x = 0;
        // Perform calculations to get x
        return x;
    })();

您可以通过编写一个辅助函数来对此进行清理:

public static T Perform<T>(Func<T> function)
{
    return function();
}

哪些可以让您写:

int Foo = Perform(() => 
    {
        int x = 0;
        // Perform calculations to get x
        return x;
    });

虽然这比第一个要好,但是我认为很难说或者比仅仅编写一个函数要好。

在非一般情况下,可以将许多特定的实现更改为在单行而不是多行上运行。在您的情况下,这样的解决方案可能是可行的,但如果不知道它是什么,我们就不可能说。在某些情况下,这是可能,但不希望有,在某些情况下,这实际上可能是更可取的。哪些当然是主观的。

答案 2 :(得分:0)

您可以在构造函数中初始化字段,然后将CalculateInitialFoo声明为本地函数。

private int _foo;

public MyType()
{
    _foo = CalculateInitialFoo();

     int CalculateInitialFoo()
     {
          int x = 0;
          // Perform calculations to get x
          return x;
     }
}

这不会改变您的代码太多,但您至少可以将方法的范围限制为仅使用该方法的地方。