了解在F#3.0中的变化来保护/底座部件使用(Understanding a change to p

2019-09-21 15:28发布

F#3.0增加了对呼叫严格的检查baseprotected成员。 我有一些像在C#以下抽象类,已protected static辅助方法由派生类使用。

public abstract class Processor {
    public abstract void Process();
    protected static void Helper(object arg) { }
}

在F#,的一些辅助方法之一被传递作为第一级的功能:

type DerivedProcessor() =
  inherit Processor()

  let init f =
    f ()

  override x.Process() =
    init Processor.Helper

它编译没有在2.0的投诉,但在3.0产生一个错误:

被保护的成员被称为或“基础”被使用。 这是只允许在直接执行的成员,因为他们无法逃脱它们的对象范围。

OK,这是很容易满足,只是包装的呼叫另一个静态成员

static member private HelperWrapper(arg) = Processor.Helper(arg)

并传递这一翻译。 但为什么?

C#与此相同的模式没有问题。

public class HappyToCompile : Processor {
    private void Init(Action<object> f) {
        f(null);
    }

    public override void Process() {
        Init(Helper);
    }
}

问题:

  1. 为什么在严格的检查补充?
  2. (和相关的)可怕的问题做什么这样一个平凡的解决方法的地址?
  3. 有没有更好的设计,这是应该鼓励?

Answer 1:

用我的心灵语言设计技巧,我猜想,F#2.0生成无法验证的代码。 见这对埃里克利珀的博客文章在C#中的一个相关问题的解释(因为C#4,IIRC已经固定)。

总之,当你创建一个F#函数你真的从创建一个新的类派生FSharpFunc<_,_>并从类中调用的受保护方法是无效的,因为它不是在继承链。

当然,而非禁止这些调用,编译器可能只是你正在做的事情(创建一个私有的方法和使用),但也许带来的好处被认为不超过执行该改进的成本。



文章来源: Understanding a change to protected/base member usage in F# 3.0