我现在一直在看 Func<> ,而且我已经设法避免它(现在)。但是,现在看起来我无法永远避开它。例如,我尝试了动态Linq,但几乎所有内容都是以Func<>表示的。我已经尝试了我的一本书(C#2008 / Deitel& Deitel)以及MSDN,但我还没有得到它。他们都直接跳入主题。
感谢您的帮助
答案 0 :(得分:33)
Func<>
是一个通用委托 - 它使用起来非常方便,因为您不必为每个参数/返回类型组合创建自己的委托。
早些时候,你必须写一些类似的东西:
public delegate long MyDelegate( int number );
public void Method( IEnumerable<int> list, MyDelegate myDelegate )
{
foreach( var number in list )
{
myDelegate( number );
}
}
您必须发布您的委托,以便用户可以正确调用您的方法。特别是当你需要一堆不同的代表时,你最终会为每个参数列表和返回类型发布一个
使用Func<>
,您只需写下:
public void Method( IEnumerable<int> list, Func<int, long> myDelegate )
{
foreach( var number in list )
{
myDelegate( number );
}
}
它与第一个代码示例相同 - Func<int, long>
定义一个带有一个整数参数并返回long值的委托。
当然,您也可以使用更长的参数列表:Func<int, int, bool, long>
仍会返回长值,而需要两个整数和一个 bool 价值。如果您希望代表没有返回值,则必须使用Action<>
,其中 void 将作为返回类型。
编辑(按要求):如何调用我的示例中的方法:
对于来电者,MyDelegate
或Func<>
的解决方案没有区别。在这两种情况下,他都有三种方法可以调用该方法:
使用lambda表示法(需要C#3.0,可能是短方法的最佳解决方案):
Method( myList, i => i * i );
使用匿名方法(需要C#2.0):
Method( myList, delegate( int i )
{
return i * i;
} );
或者使用真实方法作为参数:
Method( myList, Square );
private static long Square( int number )
{
return number * number;
}
答案 1 :(得分:12)
Func<...>
是委托类型的系列,它返回一些值,并获取一些参数;例如:
Func<int,bool>
只需要一个int并返回一个bool(返回总是在结尾);例如谓词:
int[] data = {1,2,3,4,5};
var odd = data.Where(i => i % 2 == 0);
Func<string>
是一种返回字符串的方法,例如() => "hello world";
。
Func<DateDtime, TimeSpan, DateTime>
可能类似于(when,howLong) => when + howLong;
同样地,Action<...>
执行相同但没有返回类型。
Func<...>
没有什么神奇之处 - 它只是表达委托的一种更简单的方式,而a:使用泛型(对LINQ有用),或者b:不需要你查找参数是什么;如果委托类型是模糊的(例如PipeStreamImpersonationWorker
),则很难知道它需要什么;如果将其表示为可比较的Action
,则很明显它不需要参数并返回void
。
答案 2 :(得分:10)
这可能会有所帮助。假设您每次看到Func<int, string>
时都想到自己:
interface IFuncIntString
{
string Invoke(int x);
}
也就是说,委托是实现此接口的对象。它有一个名为Invoke的方法,它接受一个int并返回一个字符串。
现在添加一个功能,您可以在呼叫中省略“调用”,并且您自己就是一名代表。
答案 3 :(得分:7)
Func<int>
(例如)是一种类型(string
是一种类型)。所以你用它来声明变量,字段,参数等。
它表示每当您要求答案时都可以执行的计算:
Func<int> f = () => DateTime.Now.Second;
// elsewhere...
Console.WriteLine( f() );
请注意如何像方法一样调用它。 Func
的许多重载版本都支持不同数量的参数。最后一个类型参数是返回类型。
Func<int, string> quoteInt = n => "\"" + n + "\"";
Console.WriteLine( quoteInt(3) );
Func
是委托类型。您可以声明自己的,但使用Func
更容易。如果您要返回void
,请使用Action
代替Func
。如果您需要out
或ref
参数,则只需声明自定义委托。
将lambda分配给Func
时,可以引用局部变量。这非常强大;这意味着Func
不仅仅是代码;它有数据。所以它就像一个具有单个方法的对象(从技术上讲它是 - 该方法称为Invoke
,并且当您调用委托时,编译器会隐式调用该方法。)
语法() =>
可以放在任何表达式之前,表示“现在不要这样做,将它延迟到以后”。它允许您初始化捕获延迟计算的委托。然后可以在委托之后放置语法()
以实际触发计算。因此后缀()
与前缀() =>
相反。
答案 4 :(得分:3)
答案 5 :(得分:1)
Func&lt; ...,T&gt;是代表。 其中T是返回类型,所有其他 - 输入参数。
答案 6 :(得分:1)
如果你曾经使用过=&gt; c#中的运算符,你可能已经使用了Funcs。你还没有明确地声明它们。
所以,如果你写一个像
这样的陈述var peopleWhoLikeBlue = people.Where(person => person.FavoriteColor == "Blue");
您将Func<Person, bool>
传递给Where()方法。
如果你想要罗嗦,你可以像这样重写那句话:
Func<Person, bool> favoriteColorIsBlue = person => person.FavoriteColor == "Blue";
var peopleWhoLikeBlue = people.Where(favoriteColorIsBlue);
你会得到相同的结果。