Skip to content

Commit 6d06e52

Browse files
Demonstrate how and_then() is a replacement to C#'s ? operator
The example is a bit complicated, but I haven't found a better one.
1 parent 23e9796 commit 6d06e52

File tree

1 file changed

+25
-4
lines changed

1 file changed

+25
-4
lines changed

src/language/nullability-and-optionality.md

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,21 +48,41 @@ if let Some(max) = max {
4848
## Null-conditional operators
4949

5050
The null-conditional operators (`?.` and `?[]`) make dealing with `null` in C#
51-
more ergonomic. In Rust, they are best replaced by using the [`map`][optmap]
52-
method. The following snippets show the correspondence:
51+
more ergonomic. In Rust, they are best replaced by using either the [`map`][optmap]
52+
method or the [`and_then`][opt_and_then] method, depending on the nesting of the `Option`.
53+
The following snippets show the correspondence:
5354

5455
```csharp
5556
string? some = "Hello, World!";
5657
string? none = null;
57-
Console.WriteLine(some?.Length); // 13
58+
Console.WriteLine(some?.Length); // Hello, World!
5859
Console.WriteLine(none?.Length); // (blank)
60+
61+
record Name(string FirstName, string LastName);
62+
record Person(Name? Name);
63+
64+
Person? person1 = new Person(new Name("John", "Doe"));
65+
Console.WriteLine(person1?.Name?.FirstName); // John
66+
Person? person2 = new Person(null);
67+
Console.WriteLine(person2?.Name?.FirstName); // (blank)
68+
Person? person3 = null;
69+
Console.WriteLine(person3?.Name?.FirstName); // (blank)
5970
```
6071

6172
```rust
6273
let some: Option<String> = Some(String::from("Hello, World!"));
6374
let none: Option<String> = None;
64-
println!("{:?}", some.map(|s| s.len())); // Some(13)
75+
println!("{:?}", some.map(|s| s.len())); // Some("Hello, World!")
6576
println!("{:?}", none.map(|s| s.len())); // None
77+
78+
struct Name { first_name: String, last_name: String }
79+
struct Person { name: Option<Name> }
80+
let person1: Option<Person> = Some(Person { name: Some(Name { first_name: "John".into(), last_name: "Doe".into() }) });
81+
println!("{:?}", person1.and_then(|p| p.name.map(|name| name.first_name))); // Some("John")
82+
let person1: Option<Person> = Some(Person { name: None });
83+
println!("{:?}", person1.and_then(|p| p.name.map(|name| name.first_name))); // None
84+
let person1: Option<Person> = None;
85+
println!("{:?}", person1.and_then(|p| p.name.map(|name| name.first_name))); // None
6686
```
6787

6888
## Null-coalescing operator
@@ -98,4 +118,5 @@ there is no need to use a substitute for it.
98118

99119
[option]: https://doc.rust-lang.org/std/option/enum.Option.html
100120
[optmap]: https://doc.rust-lang.org/std/option/enum.Option.html#method.map
121+
[opt_and_then]: https://doc.rust-lang.org/std/option/enum.Option.html#method.and_then
101122
[unwrap-or]: https://doc.rust-lang.org/std/option/enum.Option.html#method.unwrap_or

0 commit comments

Comments
 (0)