Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在不同委托中调用相同函数的结果_C#_Delegates_Memoization - Fatal编程技术网

C# 在不同委托中调用相同函数的结果

C# 在不同委托中调用相同函数的结果,c#,delegates,memoization,C#,Delegates,Memoization,我有一个函数,它接受一个Func列表,每个Func都有一个附加值。如果委托返回true,它将迭代列表并返回附加值。其中一些委托使用相同的参数调用相同的函数如何在TryFindValue方法的范围内最好地记忆此类调用的结果 函数的返回值在调用TryFindValue之间可能会更改,但在迭代列表时不会更改。我希望避免生成垃圾(例如,通过强制转换到对象来装箱/取消装箱)。理想情况下,我只需要在TryFindValue的范围内使用存储值的空间,而不是在每个代理的整个生命周期内使用,但我不知道这是否可行

我有一个函数,它接受一个Func列表,每个Func都有一个附加值。如果委托返回true,它将迭代列表并返回附加值。其中一些委托使用相同的参数调用相同的函数如何在TryFindValue方法的范围内最好地记忆此类调用的结果


函数的返回值在调用TryFindValue之间可能会更改,但在迭代列表时不会更改。我希望避免生成垃圾(例如,通过强制转换到对象来装箱/取消装箱)。理想情况下,我只需要在TryFindValue的范围内使用存储值的空间,而不是在每个代理的整个生命周期内使用,但我不知道这是否可行

public class SomeClass
{
    public bool TryFindValue(List<CondValue> list, out int value)
    {
        for (int i = 0; i < list.Count; i++)
        {
            var condValue = list[i];
            if (condValue.cond())
            {
                value = condValue.value;
                return true;
            }
        }
        value = default(int);
        return false;
    }
}

public class SomeOtherClass
{
    private List<CondValue> list;
    
    public SomeOtherClass()
    {
        list = new List<CondValue>();
        // SomeMethod(3) will be calculated twice
        list.Add(new CondValue(() => SomeMethod(3) > SomeOtherMethod(), 42));
        list.Add(new CondValue(() => SomeMethod(3) < SomeThirdMethod(), 35));
    }
    
    private float SomeMethod(int value)
    {
        // Implementation... (uses some internal or global state)
    }
    
    private int SomeOtherMethod()
    {
        // Implementation... (uses some internal or global state)
    }
    
    private int SomeThirdMethod()
    {
        // Implementation... (uses some internal or global state)
    }
}

public struct CondValue
{
    public Func<bool> cond;
    public int value;
    
    public CondValue(Func<bool> func, int value)
    {
        this.func = func;
        this.value = value;
    }
}
公共类SomeClass
{
公共bool TryFindValue(列表,out int值)
{
for(int i=0;iSomeMethod(3)>SomeOtherMethod(),42));
添加(新CondValue(()=>SomeMethod(3)
如果您将
CondValue.cond
转换为表达式树而不是
Func
,那么您可能会提出一些复杂的解决方案。我没有这样做的经验,我不建议冒险去冒险。除此之外,我没有看到一个好的解决方案,只在调用
TryFindValue
的生命周期内缓存/记忆它

我想问你:

  • 您有什么理由使用当前设置吗?
    • 这似乎是一个不必要的复杂设置。由于您只展示了一个非常抽象的示例,因此很难提出更好的替代方案
  • 例如
    somethod(3)
    是否不总是返回相同的值?
    • 您可以将该方法封装在一些缓存逻辑中(例如,在PostSharp的帮助下)。但是,如果它不一致地返回相同的值,则必须在必要时清除该缓存,这使得维护变得更加困难

您可以只返回值或空值,而不是使用附加值返回true或false的单个条件。这有什么帮助?对于下面的解决方案,我假设列表中调用同一函数的委托被添加到同一函数的列表中(这里在构造函数SomeOtherClass中)。从那里,您可以在if-else-if代码块中批处理调用相同函数和相同参数的委托,并在委托顶部手动“记忆”函数的结果

调用具有相同参数的相同函数的委托闻起来好像它们在这个if-else-if关系中是相关的。我添加了SomeFourthMethod来演示如何仍然紧凑地单独添加单个条件

如果您有改进此解决方案细节的建议(使用非nullable等),请随时在评论中提出建议

如果所有的条件都是独立的,并且有时恰好调用同一个函数,那么这个解决方案可能不合适。否则,这是我能想到的最简单、最有效的解决办法

public class SomeClass
{
    public bool TryFindValue(List<Func<int?>> list, out int value)
    {
        for (int i = 0; i < list.Count; i++)
        {
            var func = list[i];
            int? ret = func();
            if (ret.HasValue)
            {
                value = ret.Value;
                return true;
            }
        }
        value = default(int);
        return false;
    }
}

public class SomeOtherClass
{
    private List<Func<int?>> list;

    public SomeOtherClass()
    {
        list = new List<Func<int?>>();
        Add(() =>
        {
            float memoized = SomeMethod(3);
            if (memoized > SomeOtherMethod())
                return 42;
            else if (memoized < SomeThirdMethod())
                return 35;
            return null;
        });
        Add(() => SomeFourthMethod() > 4, 72);
    }

    private void Add(Func<int?> snippet)
    {
        list.Add(snippet);
    }

    private void Add(Func<bool> cond, int value)
    {
        list.Add(() =>
        {
            if (cond())
                return value;
            return null;
        });
    }

    private float SomeMethod(int value)
    {
        // Implementation... (uses some internal or global state)
    }

    private int SomeOtherMethod()
    {
        // Implementation... (uses some internal or global state)
    }

    private int SomeThirdMethod()
    {
        // Implementation... (uses some internal or global state)
    }

    private int SomeFourthMethod()
    {
        // Implementation... (uses some internal or global state)
    }
}
公共类SomeClass
{
公共bool TryFindValue(列表,out int值)
{
for(int i=0;i
{
浮动记忆=某种方法(3);
if(memoized>SomeOtherMethod())
返回42;
else if(memonizedSomeFourthMethod()>4,72);
}
专用void添加(Func代码段)
{
添加(代码段);
}
专用void Add(funct-cond,int-value)
{
列表。添加(()=>
{
if(cond())
返回值;
返回null;
});
}
私有浮点方法(int值)
{
//实现…(使用某些内部或全局状态)
}
private int SomeOtherMethod()
{
//实现…(使用某些内部或全局状态)
}
private int somethod()
{
//实现…(使用某些内部或全局状态)
}
private int SomeFourthMethod()
{
//实现…(使用某些内部或全局状态)
}
}

“函数的返回值在调用TryFindValue之间可能会发生变化”,您应该假设出于以下原因,SomeMethod(3)不一定在调用TryFindValue之间返回相同的值: