F#中的实例方法警告

时间:2013-05-16 17:44:45

标签: f#

此代码有效

  type UserNode(myid:int64, labeled:bool) = 
      static member SkypeId (x:UserNode) = x.SkypeI

      member this.SkypeI = myid

然而,这个不是:“SkypeId不是实例方法”

我认为我唯一的区别是“d”和SkypeI的终结

  type UserNode(myid:int64, labeled:bool) = 
      static member SkypeId (x:UserNode) = x.SkypeId

      member this.SkypeId = myid

我在这里想念的是什么......?

奇怪的是,它认为SkypeId是定义的静态方法....

3 个答案:

答案 0 :(得分:2)

此限制是公共语言规范(CLS)的一部分,它不是特定于F#。

CLI specification开始,CLS规则5规定:

  

在符合CLS的范围内引入的所有名称应独立于   种类,除非名称相同并通过重载解决。也就是说,虽然CTS允许单个类型对方法和字段使用相同的名称,但CLS不允许。

因此,通用类型系统(CTS)允许这样做,如下面的可编译IL显示

.class public auto ansi sealed Foo
extends [mscorlib]System.Object
{
    .method public instance void .ctor()
    {
        ldarg.0
        call instance void [mscorlib]System.Object::.ctor()
        ret
    }

    .field public int32 Bar

    .method public void Bar()
    {
        ldstr "Instance method"
        call void [mscorlib]System.Console::WriteLine(string)
        ret
    }

    .method static public void Bar()
    {
        ldstr "Static method"
        call void [mscorlib]System.Console::WriteLine(string)
        ret
    }
}

但是您无法从符合CLS的语言(如F#或C#)访问上述类的所有成员。

答案 1 :(得分:1)

member不遵循与let相同的规则,类的所有成员一次都可用(事实上,它是在某些边缘情况下拉动复杂的相互依赖性的有用技巧)。

不幸的是,解析类成员的规则在.NET语言中通常很复杂,静态和实例之间的区别有时很难实现。

我不知道是否存在针对此确切问题的语法修复,但通常避免使用相同的名称始终如您所述。

答案 2 :(得分:1)

在c#中它看起来像这样:

public class UserNode
{
    private readonly int _myid;

    public UserNode(int myid)
    {
        _myid = myid;
    }

    public static int SkypeId(UserNode x)
    {
        return x.SkypeId;
    }

    public int SkypeId
    {
        get { return _myid; }
    }
}

我们遇到两个错误: - 'xxx.UserNode'类型已经包含'SkypeId'的定义; - 并且内部静态方法“无法将表达式类型'方法组'转换为返回类型int”。 正如Leaf Garland写的那样,不能有同名的方法和属性。 但重载方法有效:

type UserNode(myid:int64, labeled:bool) = 
  static member SkypeId (x:UserNode) = x.SkypeId()

  member this.SkypeId() = myid