使用参数 Func<T> 的方法重载

5

我想创建一些重载的方法,这些方法接受一个Func参数。重载的方法应该调用具有参数中最通用类型的方法。以下是我的方法的快速示例,以及我想要调用它们的方式:

public static TResult PerformCaching<TResult, T1>(Func<T1, TResult> func, T1 first, string cacheKey)
{
    return PerformCaching((t, _, _) => func, first, null, null, cacheKey);
}

public static TResult PerformCaching<TResult, T1, T2>(Func<T1, T2, TResult> func, T1 first, T2 second, string cacheKey)
{
    return PerformCaching((t, t2, _) => func, first, second, null, cacheKey);
}

public static TResult PerformCaching<TResult, T1, T2, T3>(Func<T1, T2, T3, TResult> func, T1 first, T2 second, T3 third, string cacheKey)
{
    Model data = Get(cacheKey);

    if(data == null)
    {
        Add(cacheKey);

        data = func.Invoke(first, second, third);

        Update(data);
    }

    return data;
}

能不能像这样让它工作?另一个问题是,当func到达最终方法时会发生什么。它会使用一个参数执行它(当第一个方法被调用时),还是使用所有三个参数调用它。


1
你尝试了什么?哪些没有起作用? - Oded
2个回答

8
不,这种方法行不通。你试图将一个 Func<T1, TResult> 传递给一个接受 Func<T1, T2, T3, TResult> 的方法 - 这是不可行的。我建议改成这样:
public static TResult PerformCaching<TResult>(Func<TResult> func,
                                              string cacheKey)
{
    // Do real stuff in here
    // You may find ConcurrentDictionary helpful...
}

public static TResult PerformCaching<T1, TResult>
    (Func<T1, TResult> func, T1 first, string cacheKey)
{
    return PerformCaching(() => func(first), cacheKey);
}

public static TResult PerformCaching<T1, T2, TResult>
    (Func<T1, T2, TResult> func, T1 first, T2 second, string cacheKey)
{
    return PerformCaching(() => func(first, second), cacheKey);
}

public static TResult PerformCaching<T1, T2, T3, TResult>
    (Func<T1, T2, T3, TResult> func, T1 first, T2 second, T3 third,
     string cacheKey)
{
    return PerformCaching(() => func(first, second, third), cacheKey);
}

谢谢Jon,这个方法非常有效。我之前调用方法的顺序想错了。 - ChristiaanV
1
@ChristiaanV 我理解不了,难道只保留单个方法 PerformCaching<TResult>(Func<TResult> func, string cacheKey) 不删掉其他没必要的重载并且不限制参数数量不是更有用吗?这样仍然可以通过调用实现:PerformCaching(() => ActualMethod(1), cacheKey)PerformCaching(() => ActualMethod(1, "s", 'c', ...),cacheKey),我错在哪里了吗? - Saro Taşciyan

0

你需要将 Func<T, T1, T2> 转换为 Func<T, T1, T2, T3>。这并不难,但我不确定这是否是最佳方法。你还有其他通用问题,比如将其转换为字符串的 Model 强制转换。更好的方法可能是像 Cache.Retrieve<TResult>(string cashKey, Func<TResult> missingItemFactory) 这样的东西。然后你可以像这样调用:Cache.Retrieve("model1", () => repository.Get<Model>(myId)) 然后在你的方法中只需调用 if (data == null) data = missingItemFactory();

无论如何,下面是一个解决方案。

void Main()
{
    Func<string, string> f1 = s => "One";
    Func<string, string, string> f2 = (s1, s2) => "Two";
    Func<string, string, string, string> f3 = (s1, s2, s3) => "Three";

    Console.WriteLine(PerformCaching(f1, "one", "f1"));
    Console.WriteLine(PerformCaching(f1, "one", "f1"));
    Console.WriteLine(PerformCaching(f2, "one", "two", "f2"));
    Console.WriteLine(PerformCaching(f2, "one", "two", "f2"));
    Console.WriteLine(PerformCaching(f3, "one", "two", "three", "f3"));
    Console.WriteLine(PerformCaching(f3, "one", "two", "three", "f3"));
}

// Define other methods and classes here
public static TResult PerformCaching<TResult, T1>(Func<T1, TResult> func, T1 first, string cacheKey)
{
    return PerformCaching<TResult, T1, string, string>((t, t2, t3) => func(t), first, null, null, cacheKey);
}

public static TResult PerformCaching<TResult, T1, T2>(Func<T1, T2, TResult> func, T1 first, T2 second, string cacheKey)
{
    return PerformCaching<TResult, T1, T2, string>((t, t2, t3) => func(t, t2), first, second, null, cacheKey);
}

public static TResult PerformCaching<TResult, T1, T2, T3>(Func<T1, T2, T3, TResult> func, T1 first, T2 second, T3 third, string cacheKey)
{
    TResult data = Get<TResult>(cacheKey);

    if(data == null)
    {
        Add(cacheKey);

        data = func.Invoke(first, second, third);

        Update(data);
    }

    return data;
}

public static T Get<T>(string CashKey) { return default(T); }
public static void Add(string CashKey) { }
public static void Update<T>(T data) { }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接