Replies: 24 comments 2 replies
-
Linking this ([Question/Proposal] Immutable Parent Child API) just in case there are common discussions that come up. |
Beta Was this translation helpful? Give feedback.
-
In spite of that, I don't see a lot of attention from core team on this subject in Roslyn. I don't even know if it is something that is going to make it to C# eventually. We already duplicated the number of collection classes in dotnet core to support immutability. Perhaps @jaredpar could clarify if it is something that is going be considered in a future version at all. |
Beta Was this translation helpful? Give feedback.
-
I think related- https://github.com/AArnott/ImmutableObjectGraph |
Beta Was this translation helpful? Give feedback.
-
I believe Records, which is supposed to come in C# 8), will help me with part of my problem. I'm not sure about the parent/child I'm looking for. The LDM noted records could help with Roslyn Syntax Trees. |
Beta Was this translation helpful? Give feedback.
-
Although I'm a fan of programming with immutable objects, I'm not convinced that giving any type the ability to be either mutable or immutable at point of use is a valuable concept. I currently lean on the side of having, say, an One of the reasons for this is that a mutable collection and an immutable collection will probably be implemented very differently -- properly immutable data structures will probably be persistent, something that cannot easily be done with a type that is sometimes immutable and sometimes not. |
Beta Was this translation helpful? Give feedback.
-
The
I agree, with this feature we may still need to have separate implementations for the sake of efficiency, but new patterns can emerge, for example, one of the barriers to use "type views" for immutable collections, is that the compiler does not enforce ownership and the like, but when we do have safety checks around those concepts we might be able to use other mechanisms to provide both immutable and mutable implementations with less code; taking advantage of the compiler to prevent unwanted behaviors. However, that's not the case for, say, arrays. Using |
Beta Was this translation helpful? Give feedback.
-
If you want an immutable array type with a less bulky name, then I have one defined in my language-ext project. It's a Obviously language support would be better, but it at least reduces the default inertia toward mutable arrays. |
Beta Was this translation helpful? Give feedback.
-
Would you have to say `immutable int[]' all over the place? immutable int[] Filter(immutable int[] values) { ... } immutable int[] array = new immutable int[] { 1, 2, 3, 4, 5} How would you initialize one programmatically as opposed to my initialized array example? immutable int[] array = new immutable int[5];
array[1] = 1; // error |
Beta Was this translation helpful? Give feedback.
-
@mattwar what we need is a way to tell consumers of a type that it's immutable. Psudo-ish code for example: int[] array = new int[5]; // could also use writable int[] array to declare, but "writable" could be implicit
FillArray(array);
array[1] = 1; // no error
return array as readable int[]; // readable as opposed to writable |
Beta Was this translation helpful? Give feedback.
-
@whoisj did the return The problem with having the type system protected a type from the receiver modifying it is no guarantee to the receiver that the instance will not change. Immutable types need to have the guarantee of immutability on both sides. |
Beta Was this translation helpful? Give feedback.
-
I think not. if the return type is defined as immutable int[] arr = new [] { 1 };
val point = new Point(); Note that we should transfer the ownership when we are assigning a mutable var to an immutable one, so that we cannot mutate the first variable afterwards. var p = new C();
p.Mutate(); // OK
immutable C q = p;
p.Mutate(); // ERROR
I intended the latter. This would be a compile-time check (just like non-nullable reference types) and does not affect the type itself.
If the return type of the enclosing member is defined as |
Beta Was this translation helpful? Give feedback.
-
An idea to precise the scope of the modification to an immutable object could be to set the
In this way, any object could be immutable, it's the method who decides to apply or not an immutable state on his return value. |
Beta Was this translation helpful? Give feedback.
-
And it could be the same way for any object, including classes :
Maybe even the
|
Beta Was this translation helpful? Give feedback.
-
How does using a keyword at the call site keep you from calling a mutating method? immutable List<int> list = ...;
list.Add(5); // <-- how does the compiler know this is bad? |
Beta Was this translation helpful? Give feedback.
-
There's currently no way (that I can think of) of actually making this feature (immutable objects) safe, unless you want to implement it only for arrays (and maybe a few other built-in types) without also having a feature for class implementations that mark methods in some way that mutate the underlying class. We'd be much better off with immutable types first, which is proposed https://github.com/dotnet/roslyn/issues/159. |
Beta Was this translation helpful? Give feedback.
-
We'd need a way to mark a method as not-mutating. this hole just keeps going deeper, doesn't it? |
Beta Was this translation helpful? Give feedback.
-
In order to call a method off of an immutable object it should be declared with an immutable receiver, since For example, private int _x;
void Method() immutable // immutable receiver, i.e. `this` (turns to an attribute on the method)
{
// now the same rules for immutable vars are applied to `this`
this._x = 5; // ERROR, even though `_x` is not readonly nor immutable
this.NonMutating(); // OK, only able to call other non-mutating methods on `this`
} From there, on the call-site, the compiler just need to look at attributes on the method to verify it's safe. |
Beta Was this translation helpful? Give feedback.
-
@alrz sure, that's the way I thought it would have to go. But I was following a conversation about a keyword that would turn any type into an immutable type, without bifurcating any libraries, etc. If you have to get at the implementation of a type and decorate methods to mark them immutable, then you've got a lot more work ahead then just a language feature. |
Beta Was this translation helpful? Give feedback.
-
Immutability of the receiver does not depend on anything else but the type itself so an analyzer can detect such methods and mark them as immutable to make them usable in an immutable context outside of assembly boundaries in one go. In return, we would have compile-time guarantees on immutability without duplicating the whole type, one for "builder" and one for the immutable view. For arrays there is also an "underlying type" i.e. I suppose the issue of bifurcation also applies to non-nullable reference types (and any feature that depends on static analysis like method contracts) because every library needs to opt-in to provide required metadata for clients. I'll note that the ownership itself that is necessary for immutability enforcement is an important part of this and has been a big win for Rust (and is planned for Swift), for instance. |
Beta Was this translation helpful? Give feedback.
-
I think @CyrusNajmabadi said earlier that if you don't have to manually mark the method, then the library author will cause breaking changes without realizing it when they change the internals of the method. |
Beta Was this translation helpful? Give feedback.
-
@jnm2 I'm not arguing against having a way to make methods and types immutable. I was just pointing out that the discussion had drifted to a place where there was an implication that a simple keyword at the use site would magically turn types into immutable version of themselves, and I was trying to show that was not possible. |
Beta Was this translation helpful? Give feedback.
-
Most actual immutable types have API's for creating modified instances of themselves (with methods, etc.) Even if you could declare methods that did not directly change state as immutable or pure or whatever, and then used an immutable keyword at the use site to tell the compiler to not let any code make mutations, you would end up with immutable objects, but also not very useful objects. Immutable types, need to be designed to work within an immutable paradigm. Co-opting mutable types with compiler magic is not so interesting. |
Beta Was this translation helpful? Give feedback.
-
I do not thing immutable key word is the best way.Imuutable types is what we need. Actually,we need immutable base types to prevent some mistake can be found before running.Such as 'imint' instead of 'int'.
the better way
Same issue:(dotnet/runtime#77195) |
Beta Was this translation helpful? Give feedback.
-
Currently members of a readonly struct field cannot be assigned.
We could add the same functionality to classes using the
immutable
modifier (on locals, params and fields).Unlike readonly, immutable objects are deeply immutable and only allowed to call instance methods with an immutable receiver, i.e.
this
.The
immutable
modifier on a type would make all its methods implicitly immutable.An analyzer can suggest to make a method receiver
immutable
if it already satisfies these constraints.For the shorthand form (where the type is inferred) we can use
val
since we are maintaining "referential transparency" with immutable objects and it's safe to say that they are "values" rather than "variables."It is necessary to maintain a concept of "ownership" (a la Rust) with immutable objects, so that we can not mutate an object after it's being assigned to an immutable variable. for example:
Open question: what are the interactions with ref (including readonly ref, ref locals and ref returns)?
Open question: how this affects captures in lambdas and local functions?
Related to: https://github.com/dotnet/roslyn/issues/159, #955
Beta Was this translation helpful? Give feedback.
All reactions