If I have a class with constructor that takes an array like this:
public struct MyStruct{
Car car;
Boolean processed;
}
public class MyClass{
private MyStruct[] mCarStructs;
public MyClass(Car[] cars)
{
//So the only reason I pass Car[] in is to use it to
//populate my array of structs
mCarStructs = new MyStruct[cars.Length];
for (int i = 0; i < cars.Length; i++)
{
myCarStructs[i].car = cars[i];
myCarStructs[i].processed = false;
}
}
public void processCar(...)
{
if (DoProcess(myCarStructs[i].car))
{
myCarStructs[i].processed = true;
}
}
...
...
}
My understanding is that arrays are passed in by default as a reference. So, I dont think this is a leak and the reference passed in constructor will be nulled once constructor code completes.
So, there is no leak. Is this correct?
Thanks,
Arrays are not passed by reference, arrays are references. The reference to the array is passed by value.
As for memory leaks, the Garbage Collector is going to clean up all managed objects as soon as there are no longer any references to those objects; you don't need to worry about explicit memory management except in those cases where you're dealing with unmanaged memory (which you're not doing here).
Related
I have a question about creating an immutable struct inside a class definition. I want to define the struct outside the class but use that same struct type in the class definition while maintaining immutability. Will the code below achieve this?
namespace space
{
class Class1
{
public Struct {get; set;}
}
public Struct
{
public Struct(string strVar)
{
StructVar = strVar;
}
public string StructVar {get;}
}
}
Also, if I have a struct within a struct like:
class Class1
{
public Struct2 {get; set;}
}
public struct Struct2
{
public Struct2(string str, InStruct inStrct)
{
StrVar = str;
InStruct = inStrct;
}
public string StrVar {get;}
public InStruct InStruct {get;}
}
public struct InStruct
{
public InStruct(Array ary)
{
StrArray = ary
}
public Array StrArray {get;}
}
Does this also maintain immutability?
Lastly, if the size of the array in the InStruct is likely to be quite long, should I not use a struct at all and just put the array itself into the class definition instead? Am I just going struct crazy?
My concern is that because I'm doing a {set;} in the class definition that I'm breaking a rule somewhere. I would put the struct in the class definition itself but I didn't like to have to continuously call class constructors over and over to create each struct, that kind of seemed to defeat the purpose of using a struct in the first place.
It's a little difficult to give a complete answer without understanding exactly what you are trying to accomplish, but I'll start with a few important distinctions.
First, in C#, the struct/class distinction isn't about mutability per se. You can have a immutable class, like this one
public class CannotBeMutated
{
private string someVal;
public CannotBeMutated(string someVal)
{
_someVal = someVal
}
public string SomeVal => _someVal;
}
and a mutable struct, like this one
// This is not at all idiomatic C#, please don't use this as an example
public struct MutableStruct
{
private string _someVal;
public MutableStruct(string someVal)
{
_someVal = someVal;
}
public void GetVal()
{
return _someVal
}
public void Mutate(string newVal)
{
_someVal = newVal;
}
}
Using the above struct I can do this
var foo = new MutableStruct("Hello");
foo.mutate("GoodBye");
var bar = foo.GetVal(); // bar == "GoodBye"!
The difference between structs and classes is in variable passing semantics. When an object of a value type (e.g. a struct) is assigned to a variable, passed as a parameter to or returned from a method (including a property getter or setter) a copy of the object is made before it is passed to the new function context. When a object of a reference type is passed as a parameter to or returned from a method, no copy is made, because we only pass a reference to the object's location in memory, rather than a copy of the object.
An additional point on struct 'copying'. Imagine you have a struct with a field that is a reference type, like this
public struct StructWithAReferenceType
{
public List<string> IAmAReferenceType {get; set;}
}
When you pass an instance of this struct into a method, a copy of the reference to the List will be copied, but the underlying data will not. So if you do
public void MessWithYourSruct(StructWithAReferenceType t)
{
t.IAmAReferenceType.Add("HAHA");
}
var s = new StructWithAReferenceType { IAmAReferenceType = new List()};
MessWithYourSruct(s);
s.IAmAReferenceType.Count; // 1!
// or even more unsettling
var s = new StructWithAReferenceType { IAmAReferenceType = new List()};
var t = s; // makes a COPY of s
s.IAmAReferenceType.Add("hi");
t.IAmAReferenceType.Count; // 1!
Even when a struct is copied, its reference type fields still refer to the same objects in memory.
The immutable/mutable and struct/class differences are somewhat similar, insofar as they are both about where and whether you can change the contents of an object in your program, but they are still very distinct.
Now on to your question. In your second example, Class1 is not immutable, as you can mutate the value of Struct2 like this
var foo = new Class1();
foo.Struct2 = new Struct2("a", 1);
foo.Struct2 // returns a copy of Struct2("a", 1);
foo.Struct2 = new Struct2("b", 2);
foo.Struct2 // returns a copy of Struct2("b", 2);
Struct2 is immutable, as there is no way for calling code to change the values of StrVar or InVar once. InStruct is similarly immutable. However, Array is not immutable. So InStruct is an immutable container for a mutable value. Similar to if you had a ImmutableList<List<string>>. While you can guarantee calling code does not change the value of InStruct.StrArray to a different array, you can do nothing about calling code changing the value of the objects in the Array.
Finally, some generic advice related to your example.
First, mutable structs, or structs with mutable fields, are bad. The examples above should point to why structs with mutable fields are bad. And Eric Lippert himself has a great example of how terrible mutable structs can be on his blog here
Second, for most developers working in C# there's almost never a reason to create a user defined value type (i.e. a struct). Objects of value types are stored on the stack, which makes memory access to them very fast. Objects of reference types are stored on the heap, and so are slower to access. But in the huge majority of C# programs, that distinction is going to be dwarfed by the time cost of disk I/O, network I/O, reflection in serialization code, or even initialization and manipulation of collections. For ordinary developers who aren't writing performance-critical standard libraries, there's almost no reason to think about the performance implications of the difference. Heck, developers in Java, Python, Ruby, Javascript and many other languages get by in languages totally without user-defined value types. Generally, the added cognitive overhead they introduce for developers is almost never worth any benefit you might see. Also, remember that large structs must be copied whenever they are passed or assigned to a variable, and can actually be a performance problem.
TL;DR you probably shouldn't use structs in your code, and they don't really have anything to do with immutability.
Consider the following pseudo code:
public class SomeComponent
{
private List<DisposableFoo> _foos = new List<DisposableFoo>();
public void Start()
{
for (int i = 0; i < 5; i++)
{
var foo = new DisposableFoo();
var bar = new DisposableBar(); <-- EXPLICIT DISPOSE NEEDED?
foo.SomeFunc = x => bar.DoSomethingWithX(x);
_foos.Add(foo);
}
}
public void Stop()
{
_foos.ForEach(f => f.Dispose());
}
}
Does the infrastructure take care of Disposing any captured IDisposable variables as part of it's tear down?
Clarification:
I am not asking about best practices around managing disposable objects. My question is more about what does the infrastructure do in this instance. My understanding is that for capturing variables, behind the scenes the infrastructure creates a type that contains a field of type DisposableBar and it receives a reference to the object in the 'bar' variable. Once the infrastructure has captured that variable it seems like a 'gray area' to me about whose responsibility it is at that point to determine when the variable is no longer needed and can be disposed.
The short answer is yes most definitely. You need to call dispose on any object that is disposable. This is used to clean up unmanaged resources and dependencies.
Also NOTE: The garbage collector does not call Dispose on or look for IDisposable types.
If it is disposable within the method then it is ideal to use a using statement like so.
public void Start()
{
for (int i = 0; i < 5; i++)
{
using (var foo = new DisposableFoo())
using (var bar = new DisposableBar())
{
foo.SomeFunc = x => bar.DoSomethingWithX(x);
_foos.Add(foo);
}
}
}
If the variable is class level then your class should also implement IDisposable and dispose of the disposable objects it uses within it as well.
Here is a good link where I give more detail about disposing objects.
Another thing to keep in mind is that sometimes (in languages like C#) we can have circular dependencies (which is bad practice.) However; it happens a lot. If your object is garbage collected and there is a circular dependency it hangs around until the other object is also garbage collected and it causes the process to be ugly. It's all behind the scenes and usually isn't a big deal for most apps but being aware of this is important. Although you should not have circular dependencies you can implement IDisposable to clean up dependencies before going to the garbage collector, making this process cleaner. (Just remember having them is bad to start with... That said, Entity Framework is built on circular dependencies so go figure.)
Another NOTE: It is not uncommon to see the Dispose method added also to the destructor of an object; especially if the object is lower level, singleton, or static, to insure the disposable types are taken care of during garbage collection. This would look something like:
public class SomeClass : IDisposable
{
//pretend we implement a singleton pattern here
//pretend we implement IDisposable here
~SomeClass()
{
Dispose();
}
}
UPDATE:
To update the answer based on your clarification I believe you're asking what happens to the variable you retrieve from a disposable object, after that disposable object is disposed. This is tricky behavior and should be thought out well when developing a disposable type. Here's some code that shows the results of similar situation that might help you understand.
Also. whose responsible for this should be decided when developing the type but in most cases any information you give to the client should be left good for the client even after you're disposed. In other words, it would be best practice to NOT remove or dispose or manipulate any information you allow the user of your type to retrieve when you are disposing.
using System;
using System.Collections.Generic;
namespace Disposable_Variables_Reference
{
class Program
{
static void Main(string[] args)
{
List<string> DCNames = null;
string DCName = string.Empty;
int DCValue;
using (var disposableClass = new DisposableClass())
{
DCNames = disposableClass.Names;
DCName = disposableClass.Name;
DCValue = disposableClass.Value;
foreach (var name in DCNames) Console.WriteLine(name);
Console.WriteLine(DCName);
Console.WriteLine(DCValue);
}
foreach (var name in DCNames) Console.WriteLine(name);
Console.WriteLine(DCName);
Console.WriteLine(DCValue);
Console.Read();
}
public class DisposableClass : IDisposable
{
public List<string> Names { get; set; } = new List<string>() { "Michael", "Mark", "Luke", "John" };
public string Name { get; set; } = "Gabriel";
public int Value { get; set; } = 20;
public void Dispose()
{
Names.Clear();
Name = string.Empty;
Value = 0;
}
}
}
}
Output:
Michael
Mark
Luke
John
Gabriel
20
Gabriel
20
Names is a List (reference type) and IS NOT re-written to the output.
Name is string (immutable reference type) and IS re-written to the output.
Value is int (value type) and IS re-written to the output.
However; if you reassign Names in the Dispose() method, instead of clearing it, then it WILL ALSO be re-written. Example including just the dispose method change.
public void Dispose()
{
Names = null; //notice here we re-assign Names to null.
Name = string.Empty;
Value = 0;
}
New Output:
Michael
Mark
Luke
John
Gabriel
20
Michael
Mark
Luke
John
Gabriel
20
Knowing this the proper way to expose Names would be to leave it alone in the Dispose() method or expose name like so; returning a new list, so that any referendes to it are not removed when disposing.
private List<string> names = new List<string>() { "Michael", "Mark", "Luke", "John" };
public List<string> Names
{
get { return names.ToList() ; }
set { names = value; }
}
Of course this entire answer is for logic and clarification. There is no reason to use IDisposable in the DisposableClass example I've given.
If you have used unmanaged code in DisposableBar than it needed to be disposed, else Garbage collator will take care managed resources.
Yes and no. The proper thing to do will be to dispose manually. If this code is similar to the real app you should gather the bars in a list and dispose them after you dispose the foos. Depending on how your real code is structured you might need another strategy. If the bar is unmanaged resource you should always dispose it. In most cases the unmanaged resource is wrapped in a managed resource for example StreamReader wraps an unmanaged file handle. In these cases the object will be disposed when the managed object is garbage collected assuming that the dispose pattern is implemented correctly. The problem is that the GC is not deterministic and will run when there is memory pressure. There might be a situation where GC does not run but your app is starved for file handlers but since GC only cares about memory it does not run and the unmanaged resource is not disposed.
I am currently working with C# using the Unity3D engine and have come upon the following problem:
I created a class that has two private references to instances of another class which it has to access. Once I create multiple instances of the class and set the references I found out that all instances were using the same variable. I realized this as I was destroying an instance and just before that set the two variables holding the references to null. Immediately after doing that all other instances were throwing NullReferenceExceptions because they were still trying to access the references. The referenced objects are fine, other scripts can still access them.
Here is some pseudo code illustrating the structure:
public class Character
{
// Character data
}
public class StatusEffect
{
private Character target;
private Character originator;
public void Init(Character _Target, Character _Originator)
{
target = _Target;
originator = _Originator;
}
public void Destroy()
{
target = null;
originator = null;
}
}
In the program it would be called like this:
StatusEffect effect = new StatusEffect();
effect.Init(player1, player2);
// Time goes by
effect.Destroy();
After calling Destroy() every StatusEffect's two references will be null.
This is not only an issue when destroying StatusEffects, but also when creating new ones. As soon as I touch the references from within a new instance all StatusEffects will reference the two Characters specified by the new StatusEffect.
I do not understand why or how I can fix this issue. Can someone enlighten me on this matter?
Cheers,
Valtaroth
EDIT:
Here is the real code as requested:
I have a container class holding several StatusEffects. As soon as it starts, it initializes all of them.
public class CElementTag
{
// ..Other data..
public float f_Duration; // Set in the editor
private CGladiator gl_target;
private CGladiator gl_originator;
private float f_currentDuration;
public CStatusEffect[] ar_statusEffects;
// Starts the effect of the element tag
public void StartEffect(CGladiator _Originator, CGladiator _Target)
{
gl_originator = _Originator;
gl_target = _Target;
f_currentDuration = f_Duration;
for(int i = 0; i < ar_statusEffects.Length; i++)
ar_statusEffects[i].Initialize(gl_originator, gl_target);
}
// Ends the effect of the element tag
public void EndEffect()
{
for(int i = 0; i < ar_statusEffects.Length; i++)
{
if(ar_statusEffects[i] != null)
ar_statusEffects[i].Destroy();
}
}
// Called every update, returns true if the tag can be destroyed
public bool ActivateEffect()
{
f_currentDuration -= Time.deltaTime;
if(f_currentDuration <= 0.0f)
{
EndEffect();
return true;
}
for(int i = 0; i < ar_statusEffects.Length; i++)
{
if(ar_statusEffects[i] != null && ar_statusEffects[i].Update())
RemoveStatusEffect(i);
}
return false;
}
// Removes expired status effects
private void RemoveStatusEffect(int _Index)
{
// Call destroy method
ar_statusEffects[_Index].Destroy();
// Remove effect from array
for(int i = _Index; i < ar_statusEffects.Length - 1; i++)
ar_statusEffects[i] = ar_statusEffects[i+1];
ar_statusEffects[ar_statusEffects.Length - 1] = null;
}
}
The actual StatusEffect class is holding the two references as well as some other data it needs to work. It has virtual methods because there are some classes inheriting from it.
public class CStatusEffect
{
// ..Necessary data..
// References
protected CGladiator gl_target;
protected CGladiator gl_originator;
virtual public void Initialize(CGladiator _Target, CGladiator _Originator)
{
gl_target = _Target;
gl_originator = _Originator;
// ..Initialize other necessary stuff..
}
virtual public void Destroy()
{
gl_target = null;
gl_originator = null;
// ..Tidy up other data..
}
virtual public bool Update()
{
// ..Modifying data of gl_target and gl_originator..
// Returns true as soon as the effect is supposed to end.
}
}
That should be all the relevant code concerning this problem.
EDIT2
#KeithPayne I have a static array of ElementTags defined in the editor and saved to xml. At the beginning of the program the static array is loading the xml and stores all element tags. When creating a new element tag to use I utilize this constructor:
// Receives a static tag as parameter
public CElementTag(CElementTag _Tag)
{
i_ID = _Tag.i_ID;
str_Name = _Tag.str_Name;
enum_Type = _Tag.enum_Type;
f_Duration = _Tag.f_Duration;
ar_statusEffects = new CStatusEffect[_Tag.ar_statusEffects.Length];
Array.Copy(_Tag.ar_statusEffects, ar_statusEffects, _Tag.ar_statusEffects.Length);
}
Do I have to use a different method to copy the array to the new tag? I thought Array.Copy would make a deep copy of the source array and stored it in the destination array. If it is in fact making a shallow copy, I understand where the problem is coming from now.
From Array.Copy Method (Array, Array, Int32):
If sourceArray and destinationArray are both reference-type arrays or
are both arrays of type Object, a shallow copy is performed. A shallow
copy of an Array is a new Array containing references to the same
elements as the original Array. The elements themselves or anything
referenced by the elements are not copied. In contrast, a deep copy of
an Array copies the elements and everything directly or indirectly
referenced by the elements.
Consider this fluent version of the StatusEffect class and its usage below:
public class StatusEffect
{
public Character Target { get; private set; }
public Character Originator { get; private set; }
public StatusEffect Init(Character target, Character originator)
{
Target = target.Clone()
Originator = originator.Clone();
return this;
}
//...
}
public CElementTag(CElementTag _Tag)
{
i_ID = _Tag.i_ID;
str_Name = _Tag.str_Name;
enum_Type = _Tag.enum_Type;
f_Duration = _Tag.f_Duration;
ar_statusEffects = _Tag.ar_statusEffects.Select(eff =>
new StatusEffect().Init(eff.Target, eff.Originator)).ToArray();
// ar_statusEffects = new CStatusEffect[_Tag.ar_statusEffects.Length];
// Array.Copy(_Tag.ar_statusEffects, ar_statusEffects, _Tag.ar_statusEffects.Length);
}
Because you're passing in references to the objects via your Init() method, you're not actually "copying" the objects, just maintaining a reference to the same underlying objects in memory.
If you have multiple players with the same references to the same underlying objects, then changes made by player 1 will effect the objects being used by player 2.
Having said all that, you're not actually disposing the objects in your Destory method. Just setting the local instance references to Null which shouldn't affect any other instances of StatusEffects. Are you sure something else isn't disposing the objects, or that you haven't properly init'd your other instances.
If you do want to take a full copy of the passed in objects, take a look at the ICloneable interface. It looks like you want to pass in a copy of the objects into each Player.
public class Character : ICloneable
{
// Character data
//Implement Clone Method
}
public class StatusEffect
{
private Character target;
private Character originator;
public void Init(Character _Target, Character _Originator)
{
target = _Target.Clone()
originator = _Originator.Clone();
}
The fields aren't shared(static) among other instances. So calling target = null; in Destroy() won't affect other instances.
StatusEffect effect1 = new StatusEffect();
effect1.Init(player1, player2);
StatusEffect effect2 = new StatusEffect();
effect2.Init(player1, player2);
// Time goes by
effect2.Destroy();
// Some more time goes by
// accessing effect1.target won't give a `NullReferenceException` here unless player1 was null before passed to the init.
effect1.Destroy();
I think you did forget the Init(..) on the other instances. Every time you create an instance of StatusEffect, you need to call Init(...).
Update:
This line will clear the reference to the effect, but you never recreate it:
ar_statusEffects[ar_statusEffects.Length - 1] = null;
so the next time you call ar_statusEffects[x].Update() or Initialize() etc it will throw a NullReferenceException
If you want to clear out effects within you array, you could create an Enable bool in the effect, this way you only have to set/reset it.
for(int i = 0; i < ar_statusEffects.Length; i++)
if(ar_statusEffects[i].IsEnabled)
ar_statusEffects[i].Update();
Why don't you use a List instead? Arrays will be faster as long you don't have to shuffle in it. (like circulair buffers etc)
Thanks to Keith Payne I figured out where the problem was. I was creating a deep copy of CElementTag, but not of my ar_statusEffects array. I wrongly assumed Array.Copy was creating a deep copy of an array when it actually was not.
I implemented the IClonable interface for my CStatusEffect and use the Clone() method to create a true deep copy for each member of the static array and add it to the new tags ar_statusEffects array. This way I have seperate instances of the effects instead of references to the same static effect.
Thanks to everyone, especially Keith Payne, for their help and support!
Let me explain my situation. I have a program who reads an external connection and gives me an array of integers (or booleans). Those inputs should feed an object that has some properties (X, Y, Z, for example). So, if a read a value on array, i should write those values in the properties. Is there a way to pass those values by ref (for example) ? Thinking logically , the best way way would be pointers (property X pointing to array[0]), but these aren't very unclear to me.
I can create a way to look for changes in array (but is a very large array, +60000), then update my object. But i think this would be a bad ideia.
Sorry if i wrote any crap, i'm just starting on C#.
Some pseudo code to help.
class obj
{
int X {get; set;}
public obj(ref int x)
{
X = x;
}
}
class main
{
void main()
{
int a;
obj test = new obj(ref a);
}
}
So if: a = 10, obj.X = 10 too.
public class MyClass
{
private int[] backingArray;
public int X
{
get
{
if (backingArray == null)
return -1;
else
return backingArray[0];
}
}
public MyClass(int[] array)
{
if (array.Length > 0)
backingArray = array;
}
}
class Main
{
void Main()
{
int[] array = new int[] { 2 };
MyClass test = new MyClass(array);
array[0] = 6;
Console.WriteLine(test.X);//prints 6
}
}
Of course this only works with reference types (arrays are reference types). If you wanted to do this whole thing with a value type, you'd need to "wrap" it in some reference type. You can use a class such as the following to wrap anything if you don't have anything convenient.
public class Wrapper<T>
{
public T Value { get; set; }
}
It's not possible to use ref in the manor that you've shown in the OP. You wouldn't be able to store the value that was passed by reference. If you could, then you could end up passing some value on the stack and then having the created object that holds the reference living longer than the item on the stack. If that happened you would end up with a reference it a location in memory that no longer holds the variable you intended. This was somewhat of a gotcha in C++ that the designers of C# went out of their way to ensure can't happen (at least not without a lot of work).
Assuming I have a struct:
struct Vector
{
public int X, Y;
// ...
// some other stuff
}
and a class:
class Map
{
public Vector this[int i]
{
get
{
return elements[i];
}
set
{
elements[i] = value;
}
}
private Vector[] elements
// ...
// some other stuff
}
I want to be able to do something like: map[index].X = 0; but I can't, because the return value is not a variable.
How do I do this, if at all possible?
You should avoid mutable structs.
If you want your type to be mutable use a class instead.
class Vector
{
public int X { get; set; } // Use public properties instead of public fields!
public int Y { get; set; }
// ...
// some other stuff
}
If you want to use a struct, make it immutable:
struct Vector
{
private readonly int x; // Immutable types should have readonly fields.
private readonly int y;
public int X { get { return x; }} // No setter.
public int Y { get { return y; }}
// ...
// some other stuff
}
The compiler prevents you from doing this because the indexer returns a copy of an object not a reference (struct is passed by value). The indexer returns a copy, you modify this copy and you simply don't see any result. The compiler helps you avoid this situation.
If you want to handle such situation you should use class instead or change the way you deal with Vector. You shouldn't modify it's value but initialize it's values in constructor, more on this topic: Why are mutable structs “evil”?.
define Vector as class,
or
store value in a temporary variable
var v = map[index];
v.X = 0;
map[index] = v;
or
add function to change
map[index] = map[index].Offset()
or
let the [] operator return a setter class
class Setter { Vector[] Data; int Index; public double X { get { return Data[Index]; } set { Data[Index] = new Vector(value, Data[Index].Y); }}}
public Setter this[int i]
{
get
{
return new Setter() { Data = elements, Index= i };
}
}
Although generic classes work pretty well for many purposes, they do not provide any reasonable way to access structs by reference. This is unfortunate since in many cases a collection of structs would offer better performance (both reduced memory footprint and improved cache locality) and clearer semantics than a collection of class objects. When using arrays of structs, one can use a statement like ArrayOfRectangle[5].Width += 3; with very clear effect: it will update field X of ArrayOfRectangle[5] but it will not affect field X of any other storage location of type Rectangle. The only things one needs to know to be certain of that are that ArrayOfRectangle is a Rectangle[], and Rectangle is a struct with a public int field X. If Rectangle were a class, and the instance held in ArrayOfRectangle[5] had ever been exposed to the outside world, could be difficult or impossible to determine whether the instance referred to by ArrayOfRectangle[5] was also held by some other code which was expecting that field X of its instance wouldn't change. Such problems are avoided when using structures.
Given the way .net's collections are implemented, the best one can do is usually to make a copy of a struct, modify it, and store it back. Doing that is somewhat icky, but for structs that aren't too big, the improved memory footprint and cache locality achieved by using value types may outweigh the extra code to explicitly copy objects from and to the data structures. It will almost certainly be a major win compared with using immutable class types.
Incidentally, what I'd like to see would be for collections to expose methods like:
OperateOnElement<paramType>(int index, ref T element, ref paramType param, ActionByRef<T,paramType> proc) which would call proc with the appropriate element of the collection along with the passed-in parameter. Such routines could in many cases be called without having to create closures; if such a pattern were standardized, compilers could even use it to auto-generate field-update code nicely.