c# - F#/.NET 空实例异常

标签 c# .net f#

我有这个 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;
        }
    }
}

还有这个引用 DLL 的 F# 应用程序:

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

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

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

经过几次测试我发现除非我使用 this(例如访问实例字段),否则我不会得到 NullReferenceExpcetion。

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

最佳答案

如果您查看 IL,我怀疑您会发现它使用的是 call 而不是 callvirt。 C# 编译器始终使用 callvirt,即使对于非虚拟方法也是如此,因为它会强制执行无效检查。

这是一个错误吗?好吧,不一定。这取决于 F# 语言规范对空引用的方法调用的规定。它完全有可能声明将使用空“this”引用(非虚拟地)调用该方法,这正是发生的情况。

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

我怀疑 F# 方法可能会快一点,因为缺少空值检查...并且不要忘记空引用在 F# 中比在 C# 中更少“预期”... 可以解释这里采用的不同方法。当然,也可能只是疏忽。

编辑:我不是阅读 F# 规范的专家,但至少第 6.9.6 节向我建议这是一个错误:

6.9.6 Evaluating Method Applications

For elaborated applications of methods, the elaborated form of the expression will be either expr.M(args) or M(args).

  • The (optional) expr and args are evaluated in left-to-right order and the body of the member is evaluated in an environment with formal parameters that are mapped to corresponding argument values.

  • If expr evaluates to null then NullReferenceException is raised.

  • If the method is a virtual dispatch slot (that is, a method that is declared abstract) then the body of the member is chosen according to the dispatch maps of the value of expr.

这是否算作一个精心设计的应用程序我有点不知所措,恐怕......但我希望这至少能有所帮助。

关于c# - F#/.NET 空实例异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3752841/

相关文章:

c# - 捕获已处理的异常

.net - 如何在 vb.net 中生成 Code39 条码

c# - 如何在 NHibernate 中映射具有外键关系的两个表?

list - F# 到变量赋值的键值对列表

F# 单元测试和模式匹配断言

generics - F#:帮助创建看似动态类型的成员约束

c# - WPF 浏览器调用脚本

c# - 如何将键交换为值和将值交换为字典中的键

c# - SmtpException 批量发送 3 封或更多封邮件时

.net - RegEx判断字符串是否不包含特定字符