nicolas
nicolas

Reputation: 9825

instance method warning in F#

This code works

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

      member this.SkypeI = myid

Yet this one does not : "SkypeId is not an instance method"

The only difference I think I have is the "d" and the end of SkypeI

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

      member this.SkypeId = myid

What am I missing here... ?

Ok oddly enough it recognizes SkypeId as the static method being defined....

Upvotes: 1

Views: 279

Answers (3)

In c# it would look like this:

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; }
    }
}

We got two errors: - The type 'xxx.UserNode' already contains a definition for 'SkypeId'; - And inside static method "Cannot convert expression type 'method group' to return type int". As Leaf Garland wrote there can't be method and property with same name. But overloaded method works:

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

  member this.SkypeId() = myid

Upvotes: 1

Leaf Garland
Leaf Garland

Reputation: 3697

This restriction is part of the Common Language Specification (CLS), it is not specific to F#.

From the CLI specification, CLS Rule 5 states that:

All names introduced in a CLS-compliant scope shall be distinct independent of kind, except where the names are identical and resolved via overloading. That is, while the CTS allows a single type to use the same name for a method and a field, the CLS does not.

So the Common Type System (CTS) does allow this, as the following compilable IL shows

.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
    }
}

But you wont be able to access all the members of the above class from a CLS compliant language like F# or C#.

Upvotes: 3

Guvante
Guvante

Reputation: 19223

member does not follow the same rules as let, all members of a class are available at one time (in fact it is a useful trick to pull of complex interdependencies in some edge cases).

Unfortunately the rules for resolving class members are often complex in .NET languages and the distinction between static and instance is sometimes hard to come by.

I don't know offhand if there is a syntax fix for this exact issue but in general avoiding identical names always works as you mentioned.

Upvotes: 1

Related Questions