【问题标题】:Why does a StaticallyResolvedTypeParameter method call compile when it fails at run-time?为什么 StaticallyResolvedTypeParameter 方法在运行时失败时调用编译?
【发布时间】:2016-02-02 21:13:29
【问题描述】:

我刚刚编写了一个 C# 可以看到但调用它(即使使用有效参数)在运行时抛出的简单方法。

运行时失败的例子:

F#:

namespace Library1
type Class1() = 
  member __.Foo = "F#"
module MyModule = 
  // fails at run-time
  let inline fOnly (x:^a) : string = (^a:(member Foo: _) x)
  // works from C# and F# so I know it's not a problem with my stp
  let testFOnly () = fOnly (Class1())

C# 消费者:

namespace ConsoleApplication1
  {
    class Program
    {
      var class1 = new Library1.Class1();
      // NotSupportedException
      var result = Library1.MyModule.fOnly(class1);
      Console.ReadLine();    
    }
  }

为什么会编译,然后在运行时失败?我是不是做错了什么,或者我应该假设任何从 C# 调用 stp 方法的尝试总是会失败?那我应该attempt to hide them from C#吗?

【问题讨论】:

    标签: c# .net f# inline static-typing


    【解决方案1】:

    在 F# 中使用 inline 实际上不会在输出程序集中产生函数。

    函数被编码在一些元数据中,只有 F# 编译器可以读取然后内联插入。

    因此,您无法从 C# 调用 inline 函数

    【讨论】:

    • 调用它的 c# 编译。下面的编译和工作 let inline add x y = x + y 从 C# 调用为 var inlinedAdd = Library1.MyModule.add<int,int,int>(1,2); 所以显然你可以从 C# 调用 inline 函数?
    • @Maslow - 这让我很吃惊 - 也许编译器会创建一个备份的非内联版本?
    • 令我惊讶的是,人们对一个需要简单的添加函数才能反驳的答案表示赞同。
    【解决方案2】:

    示例中的代码错误

    Class1 有成员 Foo 而不是 X 并且编译失败

    -------------问题编辑后------------

    可以使用ILSpy查看反编译后的代码和错误来源

    反编译的 C# -

    namespace Library1
    {
        [CompilationMapping(SourceConstructFlags.Module)]
        public static class MyModule
        {
            public static string fOnly<a>(a x)
            {
                "Dynamic invocation of get_Foo is not supported";
                throw new NotSupportedException();
            }
    
            public static string testFOnly()
            {
                Class1 @class = new Class1();
                return "F#";
            }
        }
    }
    

    但是您可以从代码中看到这将起作用

    static void Main ( string [ ] args )
    {
      Console.WriteLine( Library1.MyModule.testFOnly()) ;
      Console.ReadLine();  
    }
    

    也没有理由将此作为函数调用 let testFOnly () = fOnly (Class1()) 而不是常规绑定,因为它针对的是类的不可变属性。

    let testFOnly = Class1() |&gt; fOnly

    【讨论】:

    • 我的错,只调整了 F# 的一半,使其对 SO 问题的可读性稍好,更新问题
    • 我真的很惊讶它没有嵌入对内联成员的调用,而是获取编译时值,如果它指向一个可能会做一些更有趣/更直观的事情函数而不是具有恒定值的道具/字段
    猜你喜欢
    • 1970-01-01
    • 2017-11-18
    • 1970-01-01
    • 1970-01-01
    • 2013-05-14
    • 1970-01-01
    • 1970-01-01
    • 2023-01-19
    相关资源
    最近更新 更多