无法更新结构中的可变字段?

时间:2018-11-07 22:01:22

标签: struct f# mutable

谁能告诉我为什么此Counter结构不起作用?每次调用Incr时,它总是将值重置为0。

type Counter = 
    struct

        val mutable i: int 

        member public this.Incr() =
            this.i <- this.i + 1

        member public this.Count = 
            this.i
    end

let noCounty(s:string): int = 
    let x = new Counter()
    x.Incr()
    x.Incr()
    x.Count

3 个答案:

答案 0 :(得分:2)

可变结构的语义总是令人困惑,因为在某些情况下以特定方式使用结构时会意外复制该结构-因此,最好避免在结构内部进行突变。

您可以通过将protected void onActivityResult(int requestCode, int resultCode, @Nullable final Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode == RC_SIGN_IN){ if(resultCode == RESULT_OK){ Toast.makeText(this,"Signed in!", LENGTH_SHORT).show(); } else if(resultCode == RESULT_CANCELED){ Toast.makeText(this,"Signed in canceled!", LENGTH_SHORT).show(); finish(); } } else if(requestCode == RC_PHOTO_PICKER && resultCode == RESULT_OK){ // HERE I CALLED THAT METHOD uploadPhotoInFirebase(data); } } private void uploadPhotoInFirebase(@Nullable Intent data) { Uri selectedImageUri = data.getData(); // Get a reference to store file at chat_photos/<FILENAME> final StorageReference photoRef = mChatPhotoStorageReference .child(selectedImageUri .getLastPathSegment()); // Upload file to Firebase Storage photoRef.putFile(selectedImageUri) .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { // Download file From Firebase Storage photoRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() { @Override public void onSuccess(Uri downloadPhotoUrl) { //Now play with downloadPhotoUrl //Store data into Firebase Realtime Database FriendlyMessage friendlyMessage = new FriendlyMessage (null, mUsername, downloadPhotoUrl.toString()); mDatabaseReference.push().setValue(friendlyMessage); } }); } }); } 内的x变量标记为可变变量来使其工作。根据您当前对noCounty的定义,以下各项将按预期工作:

Counter

我同意这很令人困惑。我认为逻辑是,如果将变量定义为不可变的,则编译器会在进行任何可能使它突变的调用之前将结构的值复制到新变量中。结果,编译后的代码看起来更像:

let noCounty() = 
    let mutable x = new Counter()
    x.Incr()
    x.Incr()
    x.Count

我希望编译器对此发出一些警告-因此,在这种情况下,缺少警告可能会被报告为编译器错误。 (尽管该行为可能是预期的。)

答案 1 :(得分:1)

我不知道为什么它不能像您所拥有的那样起作用,但是它会以这种方式起作用:

type Counter() = 
    [<DefaultValue>]
    val mutable i: int

    member public this.Incr() =
        this.i <- this.i + 1

    member public this.Count = 
        this.i

答案 2 :(得分:0)

如果您确实想这样做,可以:

[<Struct>]
type Counter = 
        val mutable i: int 

        member public this.Incr() =
            this.i <- this.i + 1

        member public this.Count = 
            this.i

let  mutable x = Counter() // You need to make the struct itself mutable
x.Incr()
x.Incr()
x.Count
//val it : int = 2

说实话,编译器应该抱怨这种行为。通常来说,特别是在结构中进行变异并不是一个好主意;可以,但是您需要使x本身可变,因为您正在更改结构本身(值类型)。另一个答案为您提供了一个类,它是一种引用类型。