代码之家  ›  专栏  ›  技术社区  ›  Elephantik

F#/.NET空实例奇数

  •  9
  • Elephantik  · 技术社区  · 14 年前

    我有一个C#DLL:

    namespace TestCSProject
    {
        public class TestClass
        {
            public static TestClass Instance = null;
    
            public int Add(int a, int b)
            {
                if (this == null)
                    Console.WriteLine("this is null");
                return a + b;
            }
        }
    }
    

    open TestCSProject
    printfn "%d" (TestClass.Instance.Add(10,20))
    

    没有人发起 Instance 静态变量。猜猜F应用程序的输出是什么?

    this is null
    30
    Press any key to continue . . .
    

    经过几次测试,我发现除非我使用 this

    这是预期的行为还是F#编译/CLR中的漏洞?

    2 回复  |  直到 14 年前
        1
  •  10
  •   Jon Skeet    14 年前

    我怀疑你会发现它在使用 call callvirt 如果你看一下IL。C编译器总是使用 卡尔维特

    这是虫子吗?嗯,不一定。这取决于F语言规范对空引用的方法调用的说明。它很有可能声明将使用空的“this”引用调用(非虚拟地)方法,这正是所发生的事情。

    C#碰巧指定这种取消引用将引发 NullReferenceException ,但这是一种语言选择。

    我怀疑F#方法可能会快一点,因为缺少无效性检查。。。别忘了,F#中的空引用比C#中的“预期”要少。。。那个 解释这里采取的不同方法。当然,也可能只是疏忽。

    暗示 对我来说这是个错误:

    对于方法的详细应用,表达式的详细形式将是 表达式M(args)或M(args)。

    • 如果expr的计算结果为null,则引发NullReferenceException。

    • 如果该方法是一个虚拟调度时隙(即声明为抽象的方法),则根据expr值的调度映射选择成员的主体。

    不管这算不算是一个精心设计的应用程序,恐怕我有点搞不懂。。。但我希望这至少有点帮助。

        2
  •  3
  •   Brian    14 年前

    我认为F团队认为这种行为是一个bug,在未来的版本中很可能会改变。

    有时,一个类可能会将一个方法从非虚(在版本N中)更改为虚(在版本N+1中)。这是“突破性变化”吗?如果代码是针对所使用的原始类编译的,那么这就是破坏 call callvirt . “打破变革”的概念主要是 友善的 卡尔维特

    推荐文章