什么时候我应该使用c#泛型函数

本文关键字:结果 函数 泛型 我应该 什么时候 | 更新日期: 2023-09-27 18:02:17

我一直在研究c#的泛型函数委托(Func)特性。

的例子:

// Instantiate delegate to reference UppercaseString method
Func<string, string> convertMethod = UppercaseString;
string name = "Dakota";
// Use delegate instance to call UppercaseString method
Console.WriteLine(convertMethod(name));

我正在努力想象一个现实生活中的场景,在那里它们可能在我自己的应用程序中有用。所以我想我应该把这个问题提出来。'

我非常感谢你的想法

什么时候我应该使用c#泛型函数<T,结果>

假设需要为报告目的对方法调用进行计时。出于维护原因,将计时代码放在函数内部是不可行的。

因此,通过使用Func调用,可以进行时间操作而不干扰:

static void Time<T>(Func<T> work)
{
    var sw = Stopwatch.StartNew();
    var result = work();
    Console.WriteLine(sw.Elapsed + ": " + result);
}

然后用我们要计时的函数调用它

Time(() => { return "Jabberwocky"; });
结果:

 00:00:00.0000926: Jabberwocky

下面是一个使用Funct<T,TResult>的示例,使用相同的时间motif来计时regex和string.split

var strData = "The rain in Spain";
Time((str) => { return Regex.Split(str, @"'s"); }, strData);
Time((str) => { return str.Split(); },             strData);

下面是设置

static void Time<T,S>(Func<T,S> work, T strToSplit)
{
   var sw = Stopwatch.StartNew();
   var result = work(strToSplit);
   sw.Stop();
    var joined = string.Join(", ", result as string[]);
    Console.WriteLine("{0} : {1}", sw.Elapsed, joined);
}

和结果

00:00:00.0000232 : The, rain, in, Spain
00:00:00.0000021 : The, rain, in, Spain

更新2017年的答案。这不是Func,而是它不返回的兄弟Action;我发现我在我的类上做了一种基本的日志记录形式,我使用了来自消费者的依赖注入,如下所示:

Action<string> ReportIt  { get; set; }
public void ReportStatus(Action<string> statusReporter)
{
    ReportIt = statusReporter;   
}

这个想法是状态报告是可选的,所以稍后在代码中我检查它是否可行,如果可行,我给出status:

 ReportIt?.Invoke("Running - Connection initiated");

类的使用者像

那样调用它
 piperInstance.ReportStatus( Console.WriteLine );

也可以表示为

 piperInstance.ReportStatus((str) => { Console.WriteLine(str); } );

对于一个评论来说有点长了

最好的解释用例的方法是功能性的map函数。

在c#中称为Select

假设你有一个字符串列表,map将允许你改变字符串。

如你的例子:

somewords.Select(Uppercase) or

somewords.Select(x = Uppercase(x)) or

somewords.Select(x => x.ToUpper())

但它并不局限于字符串到字符串的转换。假设您想获得所有字符串长度的列表,您可以简单地执行:

somewords.Select(x => x.Length)

上面的

将返回一个整数列表(或者在你的语言中使用的任何东西)。

一旦你开始将this与其他高阶函数结合起来,事情就变得有趣了:)

回到前面的例子,但是假设你想要最长字符串的长度。你有很多选择:

somewords.Select(x => x.Length).Max()
somewords.OrderByDescending(x => x.Length).First()
// or even
somewords.Max(x => x.Length)

可能还有更多我错过的。最后,它可以帮助你表达你的意图,而不需要做很多额外的工作(就像最后一个例子)。

注意:

在上面的任何情况下,x => x.Length都可以被任何与获取长度相同的函数替换,例如Foo。如

int Foo(string s)
{
  return s.Length;
}

所以somewords.Max(Foo)也是一样的

刚才看到了一个有趣的现实生活中的例子:

public static List<Transaction> ReadAll(Settings settings, Func<string, FileInfo[]> getFilesOfType)
{
     FileInfo[] files = getFilesOfType("CashRevenue");
     // does stuff with files
}

调用
var transactions = FileParser.ReadAll(m_status.FilesByType)

提供函数FilesByType作为参数

public FileInfo[] FilesByType (string type)
{
     return result = Files.Where(f => f.Type == type)
                 .Select(f => new FileInfo(f.LocalPath))
                 .ToArray();
}

其中Files是一个集合属性,可以使用字符串参数FilesByType

进行过滤