【问题标题】:Func<T> with out parameter没有参数的 Func<T>
【发布时间】:2009-08-15 23:45:58
【问题描述】:

我可以将带有 out 参数的方法作为 Func 传递吗?

public IList<Foo> FindForBar(string bar, out int count) { }

// somewhere else
public IList<T> Find(Func<string, int, List<T>> listFunction) { }

Func 需要一个类型,所以 out 不会在那里编译,调用 listFunction 需要一个 int 并且不允许 out in。

有没有办法做到这一点?

【问题讨论】:

    标签: c# .net linq generics func


    【解决方案1】:

    refout 不是类型参数定义的一部分,因此您不能使用内置的 Func 委托来传递 refout 参数。当然,您可以根据需要声明自己的委托:

    delegate V MyDelegate<T,U,V>(T input, out U output);
    

    【讨论】:

    • 在 C# 4 (2010) 及更高版本中(在您编写答案时未发布),可以将 T 标记为逆变,将 V 标记为协变。但是,由于U 类型的参数 (output) 通过引用 传递,U 不能标记为协变或逆变,必须保持“不变” .因此,如果您使用 C# 4 或更高版本,请考虑 public delegate V MyDelegate&lt;in T, U, out V&gt;(T input, out U output);
    【解决方案2】:

    为什么不创建一个类来封装结果?

    public class Result
    {
         public IList<Foo> List { get; set; }
         public Int32 Count { get; set; }
    }
    

    【讨论】:

      【解决方案3】:

      Func 委托家族(或 Action 就此而言)只不过是声明为类似的简单委托类型

      //.NET 4 and above
      public delegate TResult Func<out TResult>()
      public delegate TResult Func<in T, out TResult>(T obj)
      
      //.NET 3.5
      public delegate TResult Func<T1, T2, TResult>(T1 obj1, T2 obj2)
      public delegate TResult Func<T1, T2, T3, TResult>(T1 obj1, T2 obj2, T3 obj3)
      

      等等。这样的代表可以具有 out/ref 参数,因此在您的情况下,正如其他答案所指出的那样,它只是您自己自定义实现的问题。至于为什么微软默认不打包这个,想想它需要的组合数量。

      delegate TResult Func<T1, T2, TResult>(T1 obj1, T2 obj2)
      delegate TResult Func<T1, T2, TResult>(out T1 obj1, T2 obj2)
      delegate TResult Func<T1, T2, TResult>(T1 obj1, out T2 obj2)
      delegate TResult Func<T1, T2, TResult>(out T1 obj1, out T2 obj2)
      

      只有两个参数。我们甚至没有碰过ref。对于开发人员来说,这实际上会很麻烦且令人困惑。

      【讨论】:

      • 请注意,C# 函数重载无法区分delegate TResult Func&lt;T1, T2, TResult&gt;(T1 obj, T2 obj)delegate TResult Func&lt;T1, T2, TResult&gt;(out T1 obj, T2 obj)。因此,除了重载符号名称的数量之外,Microsoft 无法添加这些重载 Func 的另一个原因。
      • 有人能给我推荐一篇关于上述代表的 MSDN 文章吗?
      • @SuLlewellyn 我找不到原始的 msdn 文章,但你可以试试:docs.microsoft.com/en-us/dotnet/api/…,docs.microsoft.com/en-us/dotnet/api/…
      【解决方案4】:

      您可以将其包装在暴露正确接口并调用 FindForBar 的 lambda/delegate/function/method 中,但我怀疑 FindForBar 已将其视为 out 参数,因此您需要确保将其抛出信息还可以/安全/可取/有正确的结果(即使您可以直接传入 FindForBar,您也需要确定这一点)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-03
        • 2016-11-30
        • 1970-01-01
        • 2013-11-15
        • 1970-01-01
        • 1970-01-01
        • 2023-03-24
        相关资源
        最近更新 更多