gpt4 book ai didi

c# - 如何确保每个参数组合只执行一次方法逻辑?

转载 作者:太空狗 更新时间:2023-10-29 21:41:01 25 4
gpt4 key购买 nike

我正在设计一个类库,其中包含一堆“EnsureXXX”类的方法。只要调用代码需要某些东西而不是需要特定于参数的初始化,就会调用此方法的想法。它类似于 EnsureChildControls ASP.Net 的方法,但以参数作为鉴别器。

例如:

public static class SomeUtilityClass {
public static void EnsureSomething(string arg1, int arg2, object arg3)
{
// Logic should be called once for each args combination
}
}

public class CallerClass
{
public void Foo()
{
SomeUtilityClass.EnsureSomething("mycustomerid", 4, myData.SomeProperty);
}
public void Foo2()
{
SomeUtilityClass.EnsureSomething("mycustomerid", 4, myData.SomeProperty);
}

}

由于这种模式将在多个地方重用并经常调用,因此我必须将性能作为目标。我还必须有一个线程安全的方法。

为此,我写了一个小工具类:

public sealed class CallHelper
{
private static readonly HashSet<int> g_YetCalled = new HashSet<int>();
private static readonly object g_SyncRoot = new object();

public static void EnsureOnce(Type type, Action a, params object[] arguments)
{
// algorithm for hashing adapted from http://stackoverflow.com/a/263416/588868
int hash = 17;
hash = hash * 41 + type.GetHashCode();
hash = hash * 41 + a.GetHashCode();
for (int i = 0; i < arguments.Length; i++)
{
hash = hash * 41 + (arguments[i] ?? 0).GetHashCode();
}

if (!g_YetCalled.Contains(hash))
{
lock (g_SyncRoot)
{
if (!g_YetCalled.Contains(hash))
{
a();
g_YetCalled.Add(hash);
}
}
}
}
}

消费代码如下所示:

public static class Program
{
static void Main()
{
SomeMethod("1", 1, 1);
SomeMethod("2", 1, 1);
SomeMethod("1", 1, 1);
SomeMethod("1", 1, null);

Console.ReadLine();
}

static void SomeMethod(string arg1, int arg2, object arg3)
{
CallHelper.EnsureOnce(typeof(Program), ()=>
{
Console.WriteLine("SomeMethod called only once for {0}, {1} and {2}", arg1, arg2, arg3);
}, arg1, arg2, arg3);
}
}

输出如预期的那样:

SomeMethod called only once for 1, 1 and 1
SomeMethod called only once for 2, 1 and 1
SomeMethod called only once for 1, 1 and

我有一些与此方法相关的问题:

  1. 我认为我已正确锁定类以确保线程安全,但我是对的吗?
  2. HashSet<int>我的哈希计算方法正确吗?我特别想知道 null 是否处理是正确的,如果我可以“散列”Action以这种方式委托(delegate)。
  3. 我的方法目前只支持静态方法。如何在不发生内存泄漏的情况下转移到实例兼容方法(将实例添加为鉴别器)?
  4. 有什么方法可以避免在不探索堆栈跟踪(因为性能影响)的情况下手动将所有参数传递给实用程序方法(仅指定操作)?我担心会因为缺少外部方法的参数而引入很多错误。

提前致谢

最佳答案

这本质上是一个 memoize ,除了你的功能是无效的。但对输入参数进行比较的相同注意事项仍然有效。

Wes Dyer 讨论 how to make a generic, multi-argument memoize in this post .一般的想法是将所有参数滚动到一个匿名类型中,并将其用作字典键。

关于使这个线程安全,考虑 .NET already has concurrent collections .您不需要将非并发集合变成并发集合;只需使用提供的集合。

为了使实例方法在不泄漏的情况下工作,要么保留 WeakReference到实例或将 memoizer 的实例存储在实例本身中,以适合您的方式为准。

关于c# - 如何确保每个参数组合只执行一次方法逻辑?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8835640/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com