The problem with "long" "unsigned" "short" "long long", etc. in the C world is that they all can mean different things depending on the architecture and compiler. i32, u64, f32, etc. make it very explicit what sized object you're working with. I'm not sure that's hugely applicable in C# land as there's only, what, two compilers and two? three? hardware architectures supported.
I agree that something like 16i32 is difficult to read which is why I typically use an underscore to separate the number from the type if I need to write a literal that way (e.g. sometimes I find 0_f64 easier to grok than 0.0).
One neat thing Rust let you do is put underscores in number literals. It's great for readibility:
0xFFFF_FFFF // easier to count than 8 Fs
And you can use that with type suffixes:
let a = 255_u8;
Although in that case, you'd probably either omit u8 entirely, letting the compiler infer the type of 'a' from usage, or use a colon to give it ane explicit type.
Type suffixes are especially useful for arguments to generic functions:
You can do the same thing with C#, which is great for groupings, e.g. "2000000" becomes "2_000_000".
As a rust noob, I didn't realise rust supported the same syntax, or that you could use it to separate the type from the value (which in rust's case, I find really helps readability).
I find the rust syntax a little difficult to read. Take "16i32" for example - it's not immediately clear which part is the actual value.