Ownership
Ownership Rules
- Each value in Rust has an owner.
- There can only be one owner at a time.
- When the owner goes out of scope, the value will be dropped.
There are a few rules for your code to comply ownership rule. And as a C# developer, these 3 were the most confusing.
Copy
let x = 5;
let y = x;
Move
let s1 = String::from("hello");
let s2 = s1;
Borrow
let mut s = String::from("hello");
let r1 = &s; // no problem
let r2 = &s; // no problem
println!("{r1} and {r2}");
// Variables r1 and r2 will not be used after this point.
let r3 = &mut s; // no problem
println!("{r3}");
Copy
When I read the book and its examples, I feel like I understood it. But when I started coding, I got confused between copy, borrow, and move. Recently, while coding in C#, I realized why I was confusing copy, borrow, and move.
The example below is similar to a problem I encountered a few days ago while coding.
public class Apple{
public string Name{get;set;}
public int Total{get;set;}
public Apple(string name, int qty){
Name=name;
Total=qty;
}
}
public class Store{
public Queue<Apple> AppleBasckets {get;set;}
public Store(){
AppleBasckets = new Queue<Apple>();
}
public Apple Take(int quantity){
Apple result = null;
if(AppleBasckets.TryPeek(out var apple)){
if(apple.Name == "Fuji")
{
result = apple;
apple.Total -= quantity;
}
}
return result;
}
}
public static void Main(string[] args)
{
var store = new Store();
store.AppleBasckets.Enqueue(new Apple("Fuji",40));
store.AppleBasckets.Enqueue(new Apple("Ambrosia",20));
var result = store.Take(5);
Console.WriteLine(result.Total);
}
This prints 35 in the console. I had unconsciously assumed that assignment operator (=) meant a copy operation. My intention was to copy the value of apple to result when doing result = apple;, but this caused unintended modification because it only copies the reference, and not the object's data. In Rust terminology, this is called a mutable borrow. If you want a copy of an object in C#, you need to implement ICloneable.
Move
In the C# code above, one piece of data was referenced by two variables. This corresponds to Figure 1-1. In Rust, data is handled as shown in Figure 1-3, following the ownership model.
[Figure 1-1]: 1 data 2 owner
[Figure 1-2]: 2 data 2 owner
[Figure 1-3]: 1 data 1 owner
*All the images above are from Rust programming language book
Lesson I learned
Whenever I encounter the assignment operator (=), I should consider whether it performs a copy or just copy a reference, whether in C#, JavaScript, or Rust.