Are value types immutable by definition?

后端 未结 12 1499
陌清茗
陌清茗 2020-12-04 09:18

I frequently read that structs should be immutable - aren\'t they by definition?

Do you consider int to be immutable?

int i         


        
12条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-04 09:37

    If you take your logic far enough, then all types are immutable. When you modify a reference type, you could argue that you're really writing a new object to the same address, rather than modifying anything.

    Or you could argue that everything is mutable, in any language, because occasionally memory that had previously been used for one thing, will be overwritten by another.

    With enough abstractions, and ignoring enough language features, you can get to any conclusion you like.

    And that misses the point. According to .NET spec, value types are mutable. You can modify it.

    int i = 0;
    Console.WriteLine(i); // will print 0, so here, i is 0
    ++i;
    Console.WriteLine(i); // will print 1, so here, i is 1
    

    but it is still the same i. The variable i is only declared once. Anything that happens to it after this declaration is a modification.

    In something like a functional language with immutable variables, this would not be legal. The ++i would not be possible. Once a variable has been declared, it has a fixed value.

    In .NET, that is not the case, there is nothing to stop me from modifying the i after it's been declared.

    After thinking about it a bit more, here's another example that might be better:

    struct S {
      public S(int i) { this.i = i == 43 ? 0 : i; }
      private int i;
      public void set(int i) { 
        Console.WriteLine("Hello World");
        this.i = i;
      }
    }
    
    void Foo {
      var s = new S(42); // Create an instance of S, internally storing the value 42
      s.set(43); // What happens here?
    }
    

    On the last line, according to your logic, we could say that we actually construct a new object, and overwrite the old one with that value. But that's not possible! To construct a new object, the compiler has to set the i variable to 42. But it's private! It is only accessible through a user-defined constructor, which explicitly disallows the value 43 (setting it to 0 instead), and then through our set method, which has a nasty side-effect. The compiler has no way of just creating a new object with the values it likes. The only way in which s.i can be set to 43 is by modifying the current object by calling set(). The compiler can't just do that, because it would change the behavior of the program (it would print to the console)

    So for all structs to be immutable, the compiler would have to cheat and break the rules of the language. And of course, if we're willing to break the rules, we can prove anything. I could prove that all integers are equal too, or that defining a new class will cause your computer to catch fire. As long as we stay within the rules of the language, structs are mutable.

提交回复
热议问题