有没有办法从静态成员访问let bound字段?以下给出了指示的错误:
type Foo(x) =
let x = x
static member test() =
let foo = Foo(System.DateTime.Now.Month)
printfn "%A" foo.x //the field, constructor or member 'x' is not defined
()
私有显式字段允许从静态成员访问:
type Bar =
val private x:int
new(x) = { x=x }
static member test() =
let Bar = Bar(System.DateTime.Now.Month)
printfn "%A" Bar.x
()
文档http://msdn.microsoft.com/en-us/library/dd469494.aspx指出“显式字段不适合日常使用”,但从静态成员访问私有实例字段肯定是例行情况。此外,我不相信您可以在主构造函数中设置显式字段,这意味着如果需要从静态成员访问一个私有实例字段,则必须将所有字段移动到显式字段,并且您不能再使用主要构造函数 - 它是全部或全部。
作为您真正希望从静态成员访问私有实例字段的真实示例,请考虑一个大整数实现:BigInteger类将是不可变的,因此大整数的内部表示将保留为私有实例字段(我们称之为data
)。现在,假设您认为Add(other)
实例方法不适合不可变数据结构,并且您只想实现静态Add(lhs,rhs)
方法:在这种情况下,您需要能够访问{{1 }和lhs.data
。
答案 0 :(得分:7)
我认为你不能这样做......事实上,你不能从其他实例访问let-bound值:
type Foo() =
let x = 3
member this.Test(f:Foo) =
f.x // same error
通常,如果您需要从它所属的实例外部访问这样的值,您应该创建一个私有属性来获取值,或者使用私有字段。
<强>更新强> 这由section 8.6.2 of the spec涵盖。特别是:
实例“let”绑定在词法范围内(因此隐式私有)绑定到正在定义的对象。
也许来自F#团队的人会对这种语言行为方式的确切答案进行权衡。但是,我可以想到几个潜在的原因:
如前所述,这里有一个大致相同的类定义和创建记录的方法:
type MyClass(i:int) =
let j = i * i
member this.IsSameAs(other:MyClass) =
false // can't access other.j here
type myRecord = { isSameAs : myRecord -> bool }
let makeMyRecord(i:int) =
let j = i * i
{ isSameAs = (fun r -> false) } //obviously, no way to access r.j here
由于F#中的构造函数在概念上类似于返回类型实例的任何其他函数(例如,可以在不使用new
的情况下调用它们),因此调用MyClass 5
在概念上类似于调用{{1 }}。在后一种情况下,我们显然不希望有任何方法可以从记录的另一个实例访问makeMyRecord 5
的本地let绑定。因此,在前一种情况下,我们也无法访问绑定。
答案 1 :(得分:0)
然后,访问来自的绑定字段 静态成员肯定是例行公事 方案
你在这里是什么意思?什么是相应的C#场景(有一个例子)?
请注意,这是合法的:
type Foo() =
let x = 4
member this.Blah = x + 1
member private this.X = x
static member Test(foo:Foo) =
foo.X
也就是说,您可以将let-bound值公开为私有成员,静态可以读取/使用它。