我在看这里描述的F#中的类型的模式匹配语法:
http://msdn.microsoft.com/de-de/library/dd547125.aspx#sectionToggle14
该页面的示例(略有修改):
open System.Windows.Forms
let RegisterControl (control: Control) =
match control with
| :? Button as button -> button.Text <- "Registered."
| :? CheckBox as checkbox -> checkbox.Checked <- false
| _ -> ()
我不明白为什么我们需要引入一个新名称(“按钮”,“复选框”)以及类型检查。如果匹配成功,编译器应该知道“control”具有所需的类型,并且可以在以下表达式/语句中相应地对待它。换句话说,为什么我不能这样做:
open System.Windows.Forms
let RegisterControl (control: Control) =
match control with
| :? Button -> control.Text <- "Registered."
| :? CheckBox -> control.Checked <- false
| _ -> ()
这与"type guard" feature in TypeScript 1.4类似。
为什么F#没有那么做呢? (注意:我正在运行VS 2012。)
答案 0 :(得分:4)
您需要新名称的一个明显原因是,match
的参数是表达式:
match some.Method() with
| :? Button -> // What to do here??
当然,该语言可以支持这些符号。在这种情况下,没有技术上的原因你不能这样做,但我认为有一个很好的逻辑理由不这样做。
F#中的每个值都有一个显式声明的位置(当你使用一个值时,你总是可以去定义)。使用这种简化的:? Type
语法定义的值实际上不会有任何声明
您可以说它们是在声明原始变量的位置声明的,但这是错误的 - 因为它会有不同的类型。
或者你可以说它们是以某种隐藏的方式声明的,但这会为语言引入一个全新的概念。
那说,我可以看到为什么语法很好用。但它似乎不符合F#中变量如何运作的逻辑。
答案 1 :(得分:2)
这将为不一致的模型交易一致的模型。
您需要引入新名称并不完全正确。这非常有效:
match control with
| :? Button -> doButtonyStuff control
| :? CheckBox -> doCheckBoxyStuff control
| _ -> ()
当然,您的control
值在匹配案例正文中保持Control
。您只需要在匹配模式中进行类型检查(C#-style is
)和强制转换(C#-style as
)时引入名称。
你建议的内容很容易被想象为在投射后你在与另一个control: Control
的匹配中使用control: Button
的隐含阴影。我看到的一个问题是,它具有使匹配案例体中control: Control
无法访问的附带效果。在您的特定示例中,这可能不是什么大问题,但如果您正在检查接口类型,则可能会变得难以处理。
今天没有模式匹配结构做这样一个隐含的事情。除非你自己这样做,否则你的绑定不会被遮蔽。如果你问我,这很好。明确比隐含更好。