保存说明以供以后评估,可能吗?

问题描述 投票:-2回答:2

我想保存关于如何在以后确定值的“指令”,而不是在当前时间保存实际值。这甚至可能吗?

一个简单的C#示例:

int[] myArray = new int[2];
Dictionary<string, int> myDictionary = new Dictionary<string, int>();
//dictionary type can be changed if required

myArray[0] = 1;
myArray[1] = 2;

myDictionary.Add("total", (myArray[0] + myArray[1]) ); // Don't evaluate the value now

myArray[0] = 3;
myArray[1] = 4;

Console.WriteLine("total 2 = " + myDictionary["total"]); // Evaluate the value now
//Desired output: 7 (3+4), actual output = 3 (1+2)
c# lazy-evaluation evaluation delayed-execution
2个回答
1
投票

你可以使用(expression bodied read-only) properties

public int[] MyArray { get; set; }

public string CurrentResult => $"total: {MyArray.Sum()} ({string.Join("+", MyArray)})";

如果需要局部变量,可以使用local functions

string GetCurrentResult() => $"total: {MyArray.Sum()} ({string.Join("+", MyArray)})";

MyArray[0] = 1;
MyArray[1] = 2;
Console.WriteLine(GetCurrentResult()); // total: 3 (1+2)
MyArray[0] = 3;
MyArray[1] = 4;
Console.WriteLine(GetCurrentResult()); // total: 7 (3+4)

如果你不使用C#7,你可以使用Func<string>代表:

Func<string> GetCurrentResult = () => $"total: {MyArray.Sum()} ({string.Join("+", MyArray)})";

1
投票

您正在寻找Lazy<T>。它需要一个Func<T>,直到通过Value属性访问它才进行评估。评估完成后,将存储结果以供进一步访问。所以你的代码可能看起来像:

int[] myArray = new int[2];

var total = new Lazy<int>(() => myArray.Sum());
myArray[0] = 1;
myArray[1] = 2;
myArray[0] = 3;
myArray[1] = 4;

Console.WriteLine("total = " + total);
Console.WriteLine("total = " + total.Value);
Console.WriteLine("total = " + total);

此代码的输出是:

total = Value is not created.
total = 7
total = 7

请注意,在不调用total.Value的情况下,结果不是int,而是告诉我们表达式尚未被评估的消息。一旦调用total.Value,随后对total的访问产生该值(由于在ToString()中隐含的Console.WriteLine()调用)。

使用Lazy<T>的好处是值是持久的,而不是每次访问时都重新计算。这使得它非常适用于每次使用类时可能无法访问的类中的属性/字段,但需要很长时间才能生成值。

Edit: Based on Op's feedback Lazy<T> isn't exactly what they are looking for.

如果您总是希望每次访问时都要评估表达式,那么您需要一个方法或Func<T>。所以想象你有一个这样的类:

public class MyClass
{
    public int[] Vals {get;set;}
}

如果你想定义获得(例如)Vals总和的自定义方法,你有几个简单的选择。

A Class method

public class MyClass
{
    public int[] Vals {get;set;}
    public int SumOfVals()
    {
        return Vals.Sum();
    }
}

如果你选择类方法,你可以(可以想象)使类通用(MyClass<T>)并使用虚拟/抽象方法来实现具体的SumOfVals方法。

A Func<T> implemented in the Class

public class MyClass
{
    public int[] Vals {get;set;}
    public Func<int[], int> SumOfVals { get;set; }
}

现在,您可以在每次实例化类时将SumOfVals设置为某个自定义函数。如果你没有把它设置为任何东西,如果你试图对它做任何事情,你会得到一个NullReferenceException。

A Func<T> implemented inline

var vals = new int[2];
var sumVals = new Func<int[], int>((arr) => arr.Sum());
Console.WriteLine(sumVals(vals));

这可能是最灵活的,但这可能导致一些意大利面条代码。我建议只在类中创建一个调用MyClass的方法,或者在MyClass中创建一个方法来处理这个逻辑。

© www.soinside.com 2019 - 2024. All rights reserved.