带out参数的Func <T>


167

我可以将带有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。

有没有办法做到这一点?

Answers:


228

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

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

7
在C#4(2010)及更高版本中(在编写答案时未发布),可以标记为协变TV协变。但是,由于output类型的参数()U是通过引用传递U因此无法将其标记为协变或逆变,而必须保持“不变”。因此,请考虑public delegate V MyDelegate<in T, U, out V>(T input, out U output);是否使用C#4或更高版本。
Jeppe Stig Nielsen 2014年


24

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

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

13

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参数,因此在您的情况下,这仅是您自己执行的自定义问题,其他答案已指出。至于为什么Microsoft默认不打包,请考虑它需要的组合数量。

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。对于开发人员而言,这实际上将是繁琐且令人困惑的。


2
请注意,C#函数重载无法区分delegate TResult Func<T1, T2, TResult>(T1 obj, T2 obj)delegate TResult Func<T1, T2, TResult>(out T1 obj, T2 obj)。因此,除了重载符号名的数量之外,Microsoft无法添加这些重载的另一个原因Func
卡斯珀范登伯格

有人可以将我引荐给上述代表的MSDN文章吗?
Su Llewellyn

@SuLlewellyn我无法找到原来的MSDN文章,但你可以尝试:docs.microsoft.com/en-us/dotnet/api/...docs.microsoft.com/en-us/dotnet/api/...
nawfal

0

您可以将其包装在一个lambda / delegate / function / method中,该方法公开了正确的接口并称为FindForBar,但是我怀疑FindForBar算作out参数是有原因的,因此您需要确保将信息丢弃确定/安全/理想/具有正确的结果(即使您可以直接传入FindForBar,也需要确定这一点)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.