gpt4 book ai didi

Func + 扩展方法 + lambda 中的 C# 歧义

转载 作者:行者123 更新时间:2023-12-01 22:47:54 25 4
gpt4 key购买 nike

我一直在努力读完这篇文章:

http://blogs.msdn.com/wesdyer/archive/2008/01/11/the-marvels-of-monads.aspx

...第一页上的某些内容让我感到不舒服。特别是,我试图理解 Compose<>() 函数,并为自己编写了一个示例。考虑以下两个 Func:

Func<double, double> addTenth = x => x + 0.10;
Func<double, string> toPercentString = x => (x * 100.0).ToString() + "%";

没问题!很容易理解这两个函数的作用。

现在,按照本文中的示例,您可以编写一个通用扩展方法来组合这些函数,如下所示:

public static class ExtensionMethods
{
public static Func<TInput, TLastOutput> Compose<TInput, TFirstOutput, TLastOutput>(
this Func<TFirstOutput, TLastOutput> toPercentString,
Func<TInput, TFirstOutput> addTenth)
{
return input => toPercentString(addTenth(input));
}
}

好吧。所以现在你可以说:

string x = toPercentString.Compose<double, double, string>(addTenth)(0.4);

你会得到字符串“50%”

到目前为止,一切顺利。

但是这里有一些模棱两可的地方。假设您编写了另一个扩展方法,那么现在您有两个函数:

public static class ExtensionMethods
{
public static Func<TInput, TLastOutput> Compose<TInput, TFirstOutput, TLastOutput>(
this Func<TFirstOutput, TLastOutput> toPercentString,
Func<TInput, TFirstOutput> addTenth)
{
return input => toPercentString(addTenth(input));
}

public static Func<double, string> Compose<TInput, TFirstOutput, TLastOutput>(this
Func<double, string> toPercentString,
Func<double, double> addTenth)
{
return input => toPercentString(addTenth(input + 99999));
}
}

这里有歧义。这两个函数没有重叠的签名吗?是的。这甚至可以编译吗?是的。哪一个被称为?第二个(显然会给你“错误”的结果)被调用。如果注释掉任一函数,它仍然可以编译,但会得到不同的结果。

这看起来像是在吹毛求疵,但这里有一些东西深深地冒犯了我的情感,我无法指出它。它与扩展方法有关吗?它与 lambda 有关系吗?或者它与 Func<> 如何允许您参数化返回类型有关?我不确定。

我猜这一切都在规范中的某个地方得到了解决,但我什至不知道通过 Google 可以找到它。

救命!

最佳答案

这里没有任何含糊之处。只要完全匹配,第二个就会被调用。每当匹配不精确时,您都会得到第一个函数,因为默认情况下它将与其他所有内容完全匹配。

如果您创建 Func<double, string> ,另一个是 Func<double, double> ,在显式指定 <double, double, string> 的同时调用 .Compose ,编译器有足够的信息来确定第二个版本将是完全匹配的,因此它是所使用的版本。

但是考虑一下这个愚蠢的例子:

Func<string, string> doubleString = s => s + s;
Func<DateTime, string> dateToString = date => date.ToString();

Func<DateTime, string> composedFunction = doubleString.Compose(dateToString);
Console.WriteLine(composedFunction(DateTime.Now));

调用哪个版本?结果如何?第一个版本,输出是日期作为与其自身连接的字符串。

另一方面,如果您有一个使用 Func<double, string> 的更现实的示例和Func<double, double>并且对 Compose 的调用并不明确,调用哪个版本?

Func<double, string> toPercentString = d => d.ToString("0.0%");
Func<double, double> addTenth = d => d + 0.1;
Console.WriteLine(toPercentString.Compose(addTenth)(0.8));

第一个,因为编译器确定它与第二个完全匹配。由于我不是埃里克·利珀特 (Eric Lippert) 或乔恩·斯基特 (Jon Skeet),我什至不会尝试解释其绑定(bind)。


static void DoSomething(float f, double d) { }
static void DoSomething(double d, float f) { }

...

DoSomething(1, 1);

这是不明确的(因此无法编译)。

关于Func + 扩展方法 + lambda 中的 C# 歧义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2703289/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com