- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我一直在努力读完这篇文章:
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/
虽然我正在运行以测试此 thread 中的一些代码我发现了一件奇怪的事情,如果你考虑下面的程序 import java.util.ArrayList; import java.util.List; p
我只是很好奇为什么使用 using 指令以这种方式设计它。对于 1) struct 被视为命名空间,对于 2) 它不是: struct foo { using type0 = int; }; na
我需要在 ANTLR 中匹配一条消息,该消息包含由/分隔的 2 个字段第一个字段可以有 1..3 数字,第二个字段可以有 1..2 数字, 这不起作用 msg: f1 '/' f2; f1: DIGI
我想定义一个带有 x, y, z 坐标的 3D 矢量。可以使用(+)运算符添加向量,并可以使用length函数计算长度 如果我想编译它,我会收到以下错误: It could refer to eith
所以,今天我一直在测试 Java 的重载技术,但遇到了我无法解释的歧义。基本上,当存在带有原语及其相应包装器的可变参数方法时,编译器会提示并且无法决定选择哪一个,我不明白为什么?人类很容易决定而不是编
发现: Ambiguity while overloading the cast operator 和 C++ Operator Ambiguity 没有帮助 情况: 在容器类的内部我有: opera
我正在使用以下 XPath 片段 ancestor::contribution[1]/preceding-sibling::contribution[@speaker-reference][1] 我的
在尝试依赖可变参数模板实现一些事情时,我偶然发现了一些我无法解释的事情。我将问题归结为以下代码片段: template struct A {}; template class Z, typenam
我最近对 LALR 的研究足以写一篇 LALR generator ,并且我正在尝试为其构造一个 java 或 c# 风格的语法(其开头指定为 here )。 我知道编写解析器生成器需要额外的努力
在阅读 wikipedia article关于修订控制的文章,我发现了一些似乎定义不明确的术语,并且想知道它们是如何在现实世界中实际使用/应用的。具体来说: “主线”与“基线” “分支”与“流” “结
我有以下代码: class A{ public void print(A a){ System.out.println("A 1"); } } class B exte
考虑我试过的以下查询,有两个表,Orders 和 Customers,每个表都有列名称 CustomerID,当我尝试显示两个 CustomerID 时,只有一列显示,我不明白为什么会这样,或者我是理
我正在为基本汇编语言编写一个简单的组合词法分析器/解析器。我的问题是,在解析操作码时,我需要解析一些十六进制,它是指令计数器,可能是立即值等,以及实际的操作码。 基本上,当解析像 add 这样的东西时
我正在尝试在 mysql 中跨两个不同的数据库进行标题搜索,以匹配来自不同来源的数据。在 db1 或 db2 中,标题有时会在一个数据库中以“第一个标题”开头,而在另一个数据库中则以“第一个标题”开头
我对 token 级别的歧义有疑问。 问题看起来是这样的。我的代码看起来像这样,因此标记 t_UN1 具有更高的优先级。 t_ignore = ' \t\v\r' # whitespace ....
在 Main() 的最后一行,我在尝试执行指针操作时遇到错误,但我实际上想做的是调用我在 Foo 类中定义的乘法运算符。如果这不是调用乘法的语法,那是什么? namespace test {
在此page它说: The "00" specifier causes the value to be rounded to the nearest digit preceding the decim
我正在使用 C++ Builder 并使用 TDateTime 数据类型创建 GUI 应用程序。 当我在 TDateTime 对象上使用 MonthOf() 方法时,我得到的值比 TDateTime
$7.3.3/14 (C++03) struct A { int x(); }; struct B : A { }; struct C : A { using A::x; int x(in
我一直在开发一种适配器类,当我在 clang 下遇到问题。当定义了左值引用和右值引用的转换运算符时,您会在尝试从您的类中移出时遇到歧义编译错误(当这样的代码应该没问题时,如 operator cons
我是一名优秀的程序员,十分优秀!