【问题标题】:Overloading a method with parameter Func<T>使用参数 Func<T> 重载方法
【发布时间】:2011-05-23 19:43:58
【问题描述】:

我想创建一些接受 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;
}

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

【问题讨论】:

  • 你尝试了什么?什么不起作用?

标签: c# linq overloading


【解决方案1】:

不,这种方法行不通。您会尝试将 Func&lt;T1, TResult&gt; 传递给接受 Func&lt;T1, T2, T3, TResult&gt; 的方法 - 这根本行不通。我建议改成这样:

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);
}

【讨论】:

  • 感谢乔恩,这就像一个魅力。我在考虑调用方法的错误顺序。
  • @ChristiaanV 我就是听不懂?坚持使用单一方法PerformCaching&lt;TResult&gt;(Func&lt;TResult&gt; func, string cacheKey) 消除不必要的重载并且不限制参数数量不是更有用吗?仍将支持呼叫:PerformCaching(() =&gt; ActualMethod(1), cacheKey)PerformCaching(() =&gt; ActualMethod(1, "s", 'c', ...), cacheKey)。有什么不对吗?
【解决方案2】:

您必须从Func&lt;T, T1, T2&gt; 投影到Func&lt;T, T1, T2, T3&gt;。这并不难,但我不确定这是最好的方法。您还有其他一般问题,例如转换为模型(我将其转换为字符串)。更好的方法可能是Cache.Retrieve&lt;TResult&gt;(string cashKey, Func&lt;TResult&gt; missingItemFactory)。然后你会打电话给Cache.Retrieve("model1", () =&gt; repository.Get&lt;Model&gt;(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) { }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-30
    • 2019-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    相关资源
    最近更新 更多