rust-for-dotnet-devs
rust-for-dotnet-devs copied to clipboard
Some comments on the book
- [ ] 1. In chapter 2.2, you give
let s = &mut String::from("hello");
as an example of mutable string whilelet mut s = String::from("hello");
is more common and idiomatic. - [ ] 2. In the same chapter, you say
let str = Box::new("Hello World!");
is equivalent toString
in C# and has the typeBox<str>
, but actually it has the typeBox<&str>
.let str: Box<str> = Box::from("Hello World!");
is the way to go. - [ ] 3. In the same chapter, it is worth noting that
format!()
does not allow you to embed complex expressions in the literal (other than bare variable names), and requires you to pass them after (format!("{}", expr)
). - [ ] 4. In the same chapter, it will be good to also mention the
:#?
specifier for pretty-printing debug format. - [ ] 5. In the same chapter, you can mention that Rust also has
to_string()
, and it is given for you for free whenever you implementDisplay
. - [ ] 6. In chapter 2.4.6, you say "The
self
parameter has no type annotation since it's always the type to which the method belongs.". There are exceptions to this rule, thought (thinkself: Box<Self>
etc.), however I don't know if they should be noted as they're pretty rare and advanced use case. - [ ] 7. In the same chapter, it probably should be noted that while properties are idiomatic in C#, in Rust we prefer exposing the fields directly when possible.
- [ ] 8. In the same chapter, you say that there is no equivalent to
with
in Rust. This is not correct, because we have the struct update syntax (Struct { field1: value, field2: value, ..existing_instance }
). - [ ] 9. In chapter 2.9, you may mention that
std::ptr::eq()
is somewhat like reference equality. - [ ] 10. In chapter 2.10, you may mention that there is a common shortcut to
where
in Rust:impl<T: Trait>
. - [ ] 11. In chapter 2.13, it is probably good to mention that unlike in C#, a type isn't required to implement
Error
to be used inResult
(althought it is strongly encouraged, at least for public types). - [ ] 12. In chapter 2.14, you may mention that the
?
operator (already mentioned in the previous chapter) can also propagate anOption
, and maybe also describe the trick of using an immediately invoked closure for an option block (untiltry
blocks are stabilized). - [ ] 13. In the same chapter, you say the
!
operator has no correspondence in Rust. This is mostly true, butunwrap()
behaves similarly (ignore theOption
/Result
and cause a panic when missing). I know!
doesn't throw an exception directly in case ofnull
, but using it incorrectly will often lead to aNullReferenceException
. - [ ] 14. In chapter 2.16, you give subtyping as an example of coercion. This is not exactly true; subtyping is not a kind of coercion, and the proof is that you can use it even with nested types, where you cannot use coercions (
&'static &'static str
converts to&'a &'a str
). An example of coercion is pointer unsizing (array reference to slice reference, or concrete reference to trait object reference). - [ ] 15. In chapter 3, you say the equivalent of
static
in C# is a read-only static. I don't understand why it has to be read only; Rust has mutable statics too (via interior mutability such asMutex
or the unsafestatic mut
). - [ ] 16. In chapter 5, it may be good to mention scoped threads for sharing data without
'static
lifetime.
Stopped reading here (need to go), hope to continue read in the future... A good book 😃