- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有以下 C# 类
public class BadClass
{
public BadClass(int? bad = 1)
{
}
}
public class GoodClass
{
public GoodClass(int? good = null)
{
}
}
如您所见,它们都有可选的可空参数作为其构造函数的一部分,唯一的区别是 BadClass 将参数默认设置为 null 以外的其他值。
如果我尝试在 F# 中创建这些类的实例,这就是我得到的结果:
这很好用:
let g = GoodClass()
这会抛出 NullReferenceException:
let b = BadClass()
这会抛出一个 AccessViolationException
let asyncB = async { return BadClass() } |> Async.RunSynchronously
知道这是为什么吗?
编辑
使用 ILSpy 反编译它,这是 F# 的输出
C# 类位于名为 InteopTest [sic] 的程序集中
ILSpy 到 C#
GoodClass g = new GoodClass(null);
BadClass b = new BadClass(1);
FSharpAsyncBuilder defaultAsyncBuilder = ExtraTopLevelOperators.DefaultAsyncBuilder;
FSharpAsync<BadClass> fSharpAsync = defaultAsyncBuilder.Delay<BadClass>(new Program.asyncB@10(defaultAsyncBuilder));
FSharpAsync<BadClass> computation = fSharpAsync;
BadClass asyncB = FSharpAsync.RunSynchronously<BadClass>(computation, null, null);
FSharpFunc<string[], Unit> fSharpFunc = ExtraTopLevelOperators.PrintFormatLine<FSharpFunc<string[], Unit>>(new PrintfFormat<FSharpFunc<string[], Unit>, TextWriter, Unit, Unit, string[]>("%A"));
fSharpFunc.Invoke(argv);
return 0;
这就是IL
.method public static
int32 main (
string[] argv
) cil managed
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.EntryPointAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2050
// Code size 92 (0x5c)
.maxstack 5
.entrypoint
.locals init (
[0] class [InteopTest]InteopTest.GoodClass g,
[1] valuetype [mscorlib]System.Nullable`1<int32>,
[2] class [InteopTest]InteopTest.BadClass b,
[3] class [InteopTest]InteopTest.BadClass asyncB,
[4] class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<class [InteopTest]InteopTest.BadClass>,
[5] class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder builder@,
[6] class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<class [InteopTest]InteopTest.BadClass>,
[7] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string[], class [FSharp.Core]Microsoft.FSharp.Core.Unit>,
[8] string[]
)
IL_0000: nop
IL_0001: ldloca.s 1
IL_0003: initobj valuetype [mscorlib]System.Nullable`1<int32>
IL_0009: ldloc.1
IL_000a: newobj instance void [InteopTest]InteopTest.GoodClass::.ctor(valuetype [mscorlib]System.Nullable`1<int32>)
IL_000f: stloc.0
IL_0010: ldc.i4.1
IL_0011: newobj instance void [InteopTest]InteopTest.BadClass::.ctor(valuetype [mscorlib]System.Nullable`1<int32>)
IL_0016: stloc.2
IL_0017: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_DefaultAsyncBuilder()
IL_001c: stloc.s builder@
IL_001e: ldloc.s builder@
IL_0020: ldloc.s builder@
IL_0022: newobj instance void Program/asyncB@10::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder)
IL_0027: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<!!0> [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Delay<class [InteopTest]InteopTest.BadClass>(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<!!0>>)
IL_002c: stloc.s 4
IL_002e: ldloc.s 4
IL_0030: stloc.s 6
IL_0032: ldloc.s 6
IL_0034: ldnull
IL_0035: ldnull
IL_0036: call !!0 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync::RunSynchronously<class [InteopTest]InteopTest.BadClass>(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<!!0>, class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1<int32>, class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1<valuetype [mscorlib]System.Threading.CancellationToken>)
IL_003b: stloc.3
IL_003c: ldstr "%A"
IL_0041: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string[], class [FSharp.Core]Microsoft.FSharp.Core.Unit>, class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit, string[]>::.ctor(string)
IL_0046: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string[], class [FSharp.Core]Microsoft.FSharp.Core.Unit>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<!!0, class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit>)
IL_004b: stloc.s 7
IL_004d: ldarg.0
IL_004e: stloc.s 8
IL_0050: ldloc.s 7
IL_0052: ldloc.s 8
IL_0054: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string[], class [FSharp.Core]Microsoft.FSharp.Core.Unit>::Invoke(!0)
IL_0059: pop
IL_005a: ldc.i4.0
IL_005b: ret
} // end of method Program::main
最佳答案
对我来说,这看起来像是 F# 编译器中的错误。如果您编写一些额外的 C#:
public class OtherClass
{
private static BadClass _bc = new BadClass();
}
然后查看 IL,您会看到:
// push 1 on the stack
IL_0000: ldc.i4.1
// call Nullable<int32> constructor, leaving object on stack
IL_0001: newobj instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
// call BadClass constructor with int?
IL_0006: newobj instance void Nullabool.BadClass::.ctor(valuetype [mscorlib]System.Nullable`1<int32>)
// store in _bc
IL_000b: stsfld class Nullabool.BadClass Nullabool.OtherClass::_bc
这清楚地用 1 实例化了 Nullable`1。
而 b 的 F# 代码最终是这样的:
// push a 1 on the stack
IL_0016: ldc.i4.1
// call BadClass constructor with 1 - this fails IL verification
IL_0017: newobj instance void [Nullabool]Nullabool.BadClass::.ctor(valuetype [mscorlib]System.Nullable`1<int32>)
它在堆栈上留下一个 int
而不是 int?
。当我尝试运行此代码时,由于类型不匹配,我收到 IL 验证错误。
关于c# - F# 与 C# 类互操作,该类具有一个可选的可空参数设置为除 null 之外的任何值会导致 NullReferenceException/AccessViolationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20980929/
我试图找出如何访问 ClojureScript 中的 Javascript 对象属性。如果我事先知道属性(property)的名称,那就很容易了。获取foo.bar我只是做 (.-bar foo) I
我是 .NET 的新手。我想制作一个控制台应用程序,将 .pptx 文件转换为 .wmv。我已经使用 powerpoint interop 做到了这一点。但我有一些问题。首先,如果我构建应用程序并将其
我计划将我的许可系统的核心转移到 C++,但我仍然更喜欢使用 .NET 前端进行设计。无论如何,我刚刚读完互操作功能,并决定对其进行测试。问题是,它对我来说只是花花公子,但对任何其他用户都不起作用。我
系统管理员正在编写一些常用的管理 Power Shell 脚本。主要用于 AD 管理(更新交易所详细信息、在安全组中移动人员等) 我想使用 C# 中的这些脚本(我打算将其编写为库,供网站使用)。 我看
我想在我的应用程序中使用 COM 对象。 如何确保对象已在机器中注册? 我找到的唯一解决方案(也是 on SO)是在初始化周围使用 try-catch block : try { Foo.Ba
这个问题在这里已经有了答案: How to call Java code from C#? (4 个答案) 关闭 10 个月前。 您能给我一些关于使 C# 代码和 Java 代码互操作的建议吗?让我
我正在使用 Microsoft.Office.Interop.Excel 从 C# 创建一个 Excel 工作表,但我无法按照用户想要的方式获取页脚。 1) 如何将页脚文本加粗? 2)如何将页码放在页
我正在使用 F# 和 Excel Interop 将数据输出到 Excel 电子表格。我的第一种方法是单独设置每个单元格: worksheet.Range(range1).Value2 <- "=su
与来自 Silverlight 的 COM 控件进行交互的选项有哪些? 在我的特定项目中,我有一个旧的 ActiveX 身份验证控件,我想在我的 Silverlight 应用程序中利用它。没有太多无聊
我需要针对以下场景的一些建议: 我的 Uni 组有一个巨大的 SVN 存储库。我实际上对整个项目的子目录感兴趣(例如/trunk/projects/my_project)- 不知道它是否真的与 SVN
我有一个 .NET 程序集,它是通过 COM Interop 从 Delphi 主机调用的。据我所知,.NET 代码中任何未处理的异常都将由 .net com 互操作框架处理,并且相应的 HRESUL
我有一个程序可以在单击按钮时创建两个 pdf 文件。它在 WinForms 中使用 Microsoft Office 互操作,文件创建过程如下; 用户在程序中工作 点击按钮 程序根据一个带有书签的模板
我有一个第三方 DLL 用 Delphi“a.dll”(无源代码)编写。 这个 DLL 有一个带有这个签名的方法。 function GetAny(pFileName: String): String
想知道是否有人成功使用 JDEdwards XMLInterop 功能。我已经使用它有一段时间了(使用一个简单的 PInvoke,稍后将发布代码)。我正在寻找是否有更好和/或更强大的方法。 谢谢。 最
我正在尝试让 javafx2 与 Clojure 一起使用 - 在实现像 DoubleBinding 这样的抽象类时,我不确定 Clojure 中 super.bind(moo) 的等价物是什么。我正
有人有使用 Firebird 与 .NET 框架互操作的经验吗?如果有,进展如何? 最佳答案 我在商业桌面应用程序中使用了 firebird。 它的性能很好,直到您处理返回大型结果集的查询。在这些情况
我正在 Excel 工作表中复制并插入行,如下所示: while (rowsToAdd > 0) { // copy the existing row insert
我无法确保正确销毁托管窗口。 我有一个 HwndHost 派生类,正在 TabControl 中显示(尽管这可能不相关)。我试图在选项卡关闭时销毁托管内容(而不是在包含的窗口关闭时)。 我目前拥有 m
我有两个 python 类,它们都可以使用 COM 互操作机制独立于 VBA 编写脚本。但我希望一个能够以父子模式或工厂模式控制另一个的创建。 我已经尝试过,但无法开始工作,我已将其提炼为下面的 MC
我们在我们编写的 C# dll(程序集 A)中使用 Microsoft 提供的 COM DLL (dsofile.dll)。为了避免必须注册 COM dll,我已将对 dsofile.dll 的引用的
我是一名优秀的程序员,十分优秀!