Im 设计一个拥有一套“EnsureXXX”类方法的教室。 如果呼吁守则需要某种特定论点的初始化,那么这种方法的想法就应当被称作。 该编码与<代码>类似。 确保儿童/编码系统方法。 网上,但提出反对。
注
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);
}
}
As such pattern will be reuse at several places and called very often, I have to keep performance as a target. I also have to have a thread-safe method.
为此,我写下了一个小型公用事业类别:
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
我对这种做法有一些问题:
- I think I have properly locked the class to ensure thread safety, but am I right ?
- Is
HashSet<int>
and my method of computing the hash correct ? I m especially wondering if thenull
handling is correct, and if I can "hash" anAction
delegate this way. - My methods currently supports only static methods. How can I move to a instance compatible method (adding the instance as a discriminator) without memory leaking?
- Is there any way to avoid passing all arguments manually to the utility method (just specifying the action), without exploring the stacktrace (because of the performance impact) ? I fear a lot of bugs introduced because of a missing arguments from the outermethod.
预 收