Of all the languages I have to work with, C# is by the far funnest. I don't mind a challenge but here's an anecdote.
I occasionally find myself working with Java and its like...
Me: Ok I got this moderately complicated thing to do here, and I'd like to respect some OOP principals here. How do we do this?
Java: LOL. I'll need about 20 interfaces and your soul.
Me: Hmmm... I'll need some logic controlled "properties" on some of my objects. Can you handle that?
Java: WTF is a "property"? I only got "fields". Just kidding I know what it is I just don't care. Yea I'll be needing some methods for that. Its ok, like our entire ecosystem has a naming convention and YOU BETTER GET IT RIGHT, like its "get" and "set" before methods, but in the case of booleans its like ... who knows? "is"? LOL. Good luck bitch. Fuck you we'll never express it in language. Muwahahahahaha.
Me: Seems like a pain in the ass. Ok can I import some good repositories to make this simpler.
Java: LOL fool, don't get me started. Good luck finding the packages you need to get things done. Hope you know what exact ecosystem you're working with because there's like SO many repositories. Make sure you got the right platform X architecture X operating system X phase of the moon. Also, make sure you don't typo anything because the hackers LOVE preying on moron programmers like YOU and no one cares about rooting out the bad actors. Bwahahahahahaha,
Meanwhile, in C# land
Me: Good lord, what is that 78 character generic type signature that this method is returning where I only need to store a MERE reference to it real quick?
C#: No worries bro, just declare it as "var" and I'll infer that nonsense. Also, you can kinda use this to not worry about minor code changes in the future ;)
Me: Hmm, need to do a call back. Time to declare an interfa ...
C#: Hold on sir. Its fine. Just use the Action or Func types as argument types. One of those is surely ready to suit your needs and you can use a lambda for something anonymous or directly reference an existing member on any accessible class.
Me: Great. This method needs an options object. Time to new it up and assign properties one by one.
C#: There is an easier way bro. Pass the the object as new in the argument and use curly braces to set all of its fields (properties). Doesn't really change what's going on but its much more readable and concise than the alternative.
(I could literally go on here about how C# makes most annoyances of OOP easier here, but I will cut it off).
And then don't get me started when you add .Net Core into the mix.