F#类和结构中主要构造函数之间的行为差​​异?

时间:2014-03-27 18:55:20

标签: f# visual-studio-2013

如果我在Visual Studio Express 2013中尝试此类型定义,则会出现错误:

type Foo(bar : int) =
   struct
      member x.bar = bar
   end

如果我更改它以便它是一个班级,我不会有任何错误:

type Foo(bar : int) =
   class
      member x.bar = bar
   end

我得到的错误是:

The member 'bar' can not be defined because the name 'bar' clashes with the field 'bar' in this type or module"

如果稍微更改构造函数参数的名称,则错误消失。我理解CLR结构和类之间的差异,但我不太清楚这种行为差异的原因。谁能解释一下呢?

我主要是在问这个答案是否会消除我对F#的更深层次的误解。感谢。

1 个答案:

答案 0 :(得分:5)

虽然我无法在规范中找到相关的参考资料,但是对反编译器的一些实验表明,结构体上的主要构造函数参数总是被编译为具有相同名称的字段。对于类,使用更复杂的规则集(请参阅§8.6.1.3)来确定其编译形式,其中包括在与成员冲突时更改字段名称。

比较此结构和类的编译形式:

type S(bar: int) = struct end

type C(bar: int) =
    member x.bar = bar
public class C
{
    internal int bar@12;

    public int bar
    {
        get
        {
            return this.bar@12;
        }
    }

    public C(int bar)
    {
        this.bar@12 = bar;
    }
}

public struct S : IEquatable<Program.S>, IStructuralEquatable, IComparable<Program.S>, IComparable, IStructuralComparable
{
    internal int bar;

    public S(int bar)
    {
        this.bar = bar;
    }
}

struct的主要构造函数参数被编译为一个字段(并已分配!),即使它未被使用。另一方面,该类允许具有相同名称的成员和参数。不可否认,这并不能解释为什么,但可能有助于澄清观察到的行为。