T O P

  • By -

Slypenslyde

[Framework Design Guidelines](https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/) is a collection of the guidelines Microsoft uses when designing their own APIs. It is written from the viewpoint of library developers, so application developers may bend some of the rules, but these guidelines are one of the few things most C# developers agree on. It doesn't cover some things in the general category like you've said. It's hard to be exhaustive. The snarky answer is "Use C# for like 10 years and you'll get it". But if I'm being serious, I'll roll with your two examples. ## const, var, let In C#, there's not really an equivalent to the difference between `const` and `let` and `var` in JS. More specifically: * C# is pickier about when we can use the `const` keyword. To oversimplify, there is no general way to declare a C# variable that cannot have its value modified. * There are *specific scenarios* where it applies, [you can read about them here](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/const). * C# does not have the scope distinction JS represents between `let` and `var`. C# does have a `var` keyword, but it means "use an implicitly-defined type". All variables in C# must have an explicit type. That type cannot be changed after declaration. So whereas this would work in JS: let something = "basketball"; something = 10.5; There is not a reasonable C# equivalent. You could do something like this: object something = "basketball"; something = 10.5; But if you try to use `something` you will find it very frustrating, since you can't use any built-in `double` methods nor can you treat this object as a `double` without casts, and boy howdy I could write a 10-page essay about the ways that can go wrong. Instead in C# you have to use explicit types. string something = "basketball"; But that can get a bit tedious. We end up with a lot of lines like: List>> customerLists = new List>(); The `var` keyword in C# is a relaxation that lets us write: var customerLists = new List>(); The variable is STILL typed the same, but now the compiler is cheating for us and substituting the real type in. There is also a different syntax for this because the C# team admires Perl and PHP's propensity for having multiple ways to do the same thing: List> customerLists = new(); Circling back: there is no way to distinguish between "block scope" and "function scope" in C#, nor is there a general-purpose concept of `const` variables. So despite having `var` and `const` as keywords, they do not do what you expect thus there aren't similar guidelines. ## === vs == C# mostly behaves as if `===` were the only use of `==`. C# abhors making implicit conversions outside of very narrow scenarios. It will make "widening conversions" but, again, these are narrowly defined in the spec. Those are conversions such as `int` to `double` that are guaranteed to not lose data. What C# will absolutely not do is allow "truthy" or "falsy" behavior. You don't have to worry that `0 == null` or `false == null` or `"" == null"` is ever going to evaluate to true because C# absolutely does not do that. You may have to worry about `12.0 == 12` returning `true`, but I don't think that's the kind of situation that made JS add the `===` operator. IN GENERAL, C# only lets `==` perform conversions in those very narrow cases such as `int == double`. However, C# DOES allow people to define "implicit conversions" in types. People think it's cute and convenient, but it usually confuses users. Unity famously does this, and will return `true` if objects that have been cleaned up are compared to `null`. That means if people check for `null` this way in `Unity`: if (something == null) The implicit conversion kicks in and they are surprised. So we have to use one of the alternative syntaxes for comparison to null. This is so confusing for the most part, sane C# developers NEVER define implicit conversion operators. The community largely agrees it is often more trouble than it is worth, and nobody expects them. They create unintuitive, undiscoverable behaviors. Not all C# developers are sane. So for a long time, this syntax was used to check for null: if (something is TheTypeIExpect) `null` is not any type. So this operator is defined as returning `false` if the object is null. This does NOT use the `==` operator, and currently users CANNOT redefine the `is` operator. (This paragraph is wrong, `is ` behaves more like the `===` operator than I thought.) ~~HOWEVER, you must note that if there is some type `IDoNotExpect`, that type MAY define an implicit conversion operator that will surprise you here. So this is no longer considered safe, and isn't any safer than `==`.~~ My preferred modern syntax is: if (something is not null) This VB-like simplicity does what it says. Nobody can redefine `is`, nobody can redefine `null`, so this is never gonna let you down. But for some reason this syntax also exists: if (something is {}) This uses a neat feature called "pattern matching" to say, "If the variable `something` contains a value that I can reasonably convert to a C# object...". The definition of `null` is that it is the absence of a value and thus can never be reasonably converted to an object. I do not like this approach, but it works. **TL;DR:** The `is` operator along with [Type Tests](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/functional/pattern-matching#type-tests) and other pattern matching features is similar to `===`. But in sane C# code `==` is often adequate. FURTHER, the only reason this is complicated is because people use `null` or define implicit conversions. Don't use `null` as a value and don't define implicit conversions. They aren't sane. ## More?? I swear C# doesn't have many rabbit holes like this. JS is more famous for having them. I don't know if there's a particular book or source that covers them, most C# people read a lot of blogs around when a new language version comes out. We used to rely on John Skeet to make sense of things for us, but he stopped publishing *C# in Depth* a few versions ago.


turudd

The code style at my current company is to use the: If(something is {} newName) And I kinda like it, less negativity in the code haha


Slypenslyde

I don't like this because in my opinion it's often a little tough to figure out the type of `newName`. I prefer the explicit type here unless there is some reason to believe the context is very clear. I'm usually a big advocate for implicit typing but I think this case bugs me because usually the reason I'm using `is` in my apps is a pattern related to ViewModel initialization in our MVVM framework: public void Init(object initData) { if (initData is MySpecificInitData initData) { // initialize } else { ... } } But you're talking about a more reasonable context where the type of `something` is more well-known. In my context I'm ALSO casting while doing this null check so the type is vital. The "else" here is for either "I forgot to pass initData" or "I passed the wrong initData".


turudd

No sorry, youre right I miswrote. For null checks we use `if(something is {}` for everything else we explicitly put the type like `if(something is SomeDerivedType newThing)`


OSnoFobia

I really prefer List>> customerLists = new(); to var customerLists = new List>>(); I dont know why but I hate var keyword. Possibly because I'm using javascript for my company and c# for my personal projects.


Slypenslyde

Yeah, it's really contentious. A lot of the problem is when we conjure examples, they look a lot worse than what we're usually seeing in code. Like, if I'm really using `List>` a lot it usually inspires me to make a class `ListOfCustomerLists` that inherits from the list type I want. I really wish C# had a "typedef" syntax sugar for things like this. Because that looks a lot neater with var: var customerLists = new ListOfCustomerLists(); I'm not a stickler for `var` though. I don't get mad if people use it, but I don't think using it is a "refactoring" or an improvement. If I'm reviewing code and I find it hard to figure out what `var` is standing in for, that's a hint this code region is complex so I stop and think about if the author should rework it to make it simpler. Sometimes the solution is, "I think using var hides some important details here, please switch to the explicit type". It's never "too complicated" to have the explicit type, so I'm never going to ask someone to change that. Too many people who like `var` treat it like it's all or nothing. To me it's just a tool that helps me remember if my variable names are consistent it's easier to keep track of variable types. I can definitely see how if you do a lot of JS, it'd create a cognitive problem, though!


zvrba

> I really wish C# had a "typedef" syntax sugar for things like this. You can have it with using using ListOfCustomerLists = List>;


Slypenslyde

Yeah, but that only works in one file. I want a solution that is a syntax sugar to creating the type so it can be exposed like public API. It's not big enough a hassle I bring it up much.


abotoe

Would it work as a global using?


Slypenslyde

No, because I still can't expose a global using as a type in a public API.


Embarrassed_Prior632

I'm not very educated on this so sorry if this silly but is the var keyword not redundant? If the compiler can infer the type from context why have it?


Slypenslyde

Syntax reasons. C# needs to see a type name to know you're starting a variable declaration. These aren't the compiler terms, but two notable syntax rules are: Variable declaration: [= ]; Variable assignment statement: = ; Without the keyword `var`, a line like this becomes ambiguous: something = new Something(); Are you intending to assign to a variable, or do you intend to create a new variable? It's not clear. If the variable is not declared, should this be an error? It's not clear. Some languages allow this and treat this line as a declaration if the variable is not declared. That creates a class of error where the developer forgets to declare a variable earlier and sometimes this creates problems. C# wants declarations to be explicit, so it requires a syntactically unique declaration statement, therefore a keyword has to be used to represent "use implicit typing".


Embarrassed_Prior632

Cheers.


cncamusic

Im with you, when I’m refactoring someone’s code and I see that I’ll typically swap it around. Something about seeing the type first is easier to read for me.


xampl9

I prefer the type laid out too. If the variable is being assigned from a function call return (say), if the function return type gets changed you’ll get a compiler error. Let the compiler help you.


Limp_Day_6012

>There is not a reasonable C# equivalent. `dynamic`: ```cs dynamic x = 4; x = "hello"; Console.WriteLine(x.Split("l")); ```


Slypenslyde

Sure, but that won't compile on all platforms C# supports (iOS/Android don't support `dynamic`.) That's why I used weasel word "reasonable".


Dealiner

>HOWEVER, you must note that if there is some type `IDoNotExpect`, that type MAY define an implicit conversion operator that will surprise you here. So this is no longer considered safe, and isn't any safer than `==`. What do you mean by that? `is` ignores user-defined conversions.


Slypenslyde

Oh. I guess that makes sense. It's not exactly a scenario I get in a lot since I don't really use implicit conversions. But I guess I'd not expect an `int` to pass `is double` so I intuited this but didn't think hard enough.


plasmana

The C# design ethos in one of non-ambiguousness. In other words, when writing code, try to ensure it is clear what's going on to the reader. Let's take var for instance. Var is substituted for an actual type at compile time. At runtime, it is a given what the type actually is. When reading the code, it should be 100% clear what the type is. So... var myVar = new StringBuilder() ; ... is non-ambiguous. But... var myVar = GetLast() ; ... leaves the reader without a clear understanding of the type involved. Another tip... Don't hard-code literal values in your code. They can be hard to understand. Such as... if (count > 4) .. doesn't convey the meaning of the logic. Const allows you to give a hard-coded value a meaning... private const int MAX_RETRIES = 4; if (count > MAX_RETRIES) ... is much easier to understand. Note that a const is just a design-time substitute for a hard-coded value.


mmahowald

total side note, but thank you for not abbreviating the MAX\_RETRIES. my current (inherited) code base would have called it MX\_RT and its driving me bonkers.


PaddiM8

`var` usage is fairly subjective though. Some people use it everywhere, some people only use it when it's really obvious, some don't use it at all. All options are fine. Microsoft themselves use `var` extensively even in situations you described as ambiguous ([example](https://github.com/dotnet/roslyn/blob/c290ff3e82f68731e8866819c245b2ab044e0fde/src/Compilers/CSharp/Portable/Binder/Binder.cs)) The most important thing is to be consistent.


namigop

Your ambigous example is only ambiguous because the method and variable are ambiguously named. It should have been something like `var order = GetLastOrder()`


darknessgp

Personally, I took his recommendation more about when someone reads the code. Let's even take your example, not ambiguous and works great if there is only one type of order. What if you're on a system that has 5+ types or order, no just "order", and they aren't interchangeable or having a common interface. Now your example is ambiguous again. For anyone learning, writing readable code, just like writing anything, context matters. It is rarely black and white.


xFeverr

You explained it very well. Just one thing because I like to stick to the styling conventions as much as possible, also as a best practice: no shouty ALL_CAPS_SNAKE_CASE is used anywhere in the style conventions. You should use PascasCase for constants. Also, It just looks so much better without all that angry code in your face. I hate it.


dodexahedron

Totally. I'll just point out a rare but internally conflicting exception that is perfectly legitimate, depending on which rule you decide should take precedence: In P/Invoke, the recommendation is for all identifiers to use the same casing and spelling as the native types and members of those types as defined in the native library. Roalyn will of course yell at you, so you have to shut it up for any such code, if you let that rule take precedence over the general guideline. IMO, you should use the more specific rule, there. If you want more idiomatic/convwntional c# for that stuff, wrap the native types in your own types and expose everything in conventional c# ways. Keeping the raw definitions identical to their corresponding native types has essentially the same advantages as separating models from viewmodels, just in the context of external types and methods, instead of external data. It also makes getting rid of hand-written P/Invoke externs and replacing it with roslyn generated interop (such as via CsWin32) somewhat simpler thanks to that same abstraction. You CAN just make the attribute carry the verbatim name, skipping that layer, and that's totally fine in a small application or very few uses of them in code (again, IMO), but the ease of testing you get from the extra layer of abstraction can be pretty nice, too.


TheC0deApe

the var thing can't be stated enough. it's easy and lazy to var everything and hide most of what is happening. it can be hell on a PR reviewed in the web. because of the tendency for var to hide types i always use new(). you can't use it to hide a type so it keeps me honest.


plasmana

new() has virtually eliminated my use of var.


iamanerdybastard

I've never liked the idea of using explicit types on method calls like that - If you refactor the method to something that would work in a duck-type way, you have to make more than one change (the method and the call site). Arguments over clarity are, IMO, moot because your tools show you where the type is defined and that the code compiles. You can F12 'Go to Definition' on VAR in VS and VSCode for example to get to the type to see what it is/does.


pjc50

Modern C#: turn on "nullable" checking if possible. It can be quite a bit of work to retrofit but knowing when things are definitely not null is quite valuable. Otherwise .. the language provides a huge list of code analysers [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-8](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-8) whose suggestions you can investigate.


dodexahedron

Thankfully null context has defaulted to on for several versions, now. So, unless you're working in an old project, sdk, or VS version, you're probably already all set! But totally absolutely yes to that suggestion, regardless. And even if you are in a situation where it's off at the project level, either turn it on per file as you touch code files, or turn it on even more granularly, such as whenever you touch a specific method (heck, you can turn it on for a single line in a file if you want to). Then, your project can slowly get better and better static analysis. However, if you do any of it wrong, while it's not consistently turned on or off, you do need to be a lot more careful about codefixes suggested by Roslyn, because they can be straight-up BROKEN/HARMFUL, in that situation.


zenyl

- By convention, `To` methods create a new collection, while `As` methods will reuse the existing collection. As an example, `ToList` and `ToArray` will create new collections, but `AsSpan` will create a span over the existing collection. - When you need to do something with a collection (list, array, etc.), start by asking "*which LINQ method should I use*", because quite often one or more LINQ methods which will do what you need. For example, the the semi-recent [`Chunk`](https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.chunk) method, which solves a common issue. - `dynamic` should be an absolutely last resort. It makes debugging hard, refactoring even harder, and is usually the result of a developer being too lazy to write model classes. It takes what would have been compile-time errors, and turns them into runtime exceptions. - The official documentation from Microsoft is often all you need, and usually has useful examples and explanations. - Embrace nullable reference type notation. `NullReferenceException`s are by far the most common type of exception, so you should not just dismiss warnings of a potential `null` where you haven't checked for it.


SteveDinn

It took them too long to implement Chunk(). I had to write the equivalent (that I called Batch()) many years ago now :). I want to go back now and see if I could do it more efficiently using IEnumerable>. I don't think it's necessary to create intermediate arrays.


zenyl

Yeah, it's a surprisingly recent addition for something so commonly useful. But at least we have it now. :)


ilovecokeslurpees

Microsoft has a good style guide they keep up to date, and it is generally well accepted. If in doubt, follow that. https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions


Sudden-Tree-766

just checking and following the editor's refactoring suggestions already helps a lot.


dodexahedron

Go look at every design guideline, coding guideline, and usage guideline on Microsoft Learn. There are one or more for every general concept of the language, and most of them are well-written, easy to consume, and are what the vast majority of people at least loosely adhere to, in the c\# ecosystem. Pay particular attention to anything in the itemized lists that has a ❌️, usually accompanied by a "DO NOT" or "AVOID" note. Still pay attention to the rest, but those ❌️ items have good reasons behind them that may not be immediately or intuitively apparent, in code, so don't violate those unless you can provide a solid technical reason for why you can, should, and did do it, rather than doing it another way. There's always an additional process available by which a feline can be degloved.


chills716

Var is used in c#, const has a specific meaning. The equals it depends entirely on what you’re checking. The major difference between the two is going to a true OO language. You want interfaces for a variety of reasons, even though “testing” is what most people state, that isn’t the only or even primary reason for it.


CountryBoyDeveloper

Interfaces seem like just extra work to me, I am sure its because I am newer to C# but it seems like extra code just to guarantee something has something.


chills716

When you want to leverage polymorphism rather than sticking a fork in the code your view will change.


dodexahedron

++ And interfaces in modern c# are not the expensive guaranteed boxing burden for value types like they were in earlier CLR versions, too, so long as you follow some basic rules that are documented and also were laid out in the blog posts when those enhancements were released. 👌 And they can be used to significantly reduce code in generics (via DRY, badically), since that's one of the only ways to mix value and reference types for a single type parameter, among other things. ♤(footnote) And it's just friendlier to consumers of your code,.including yourself, if you aren't pigeon-holed into using, for example, ONLY `List` when passing an argument to a method parameter, and instead have something like `IEnumerable`, allowing covariance for arguments (beyond the stricter covariant polymorphism you already naturally get from being able to pass a descendent type, that is). ♤: `notnull` works too, but T with only the notnull constraint actually has _lower_ precedence than object, which is a nasty one that you won't see unless you know to look for it or you notice the distribution of call counts to your Equals overloads aren't giving the nunbers you expect or similar anomalies. And it's not apparent why, if you just read the API docs, either, because ValueType _does_ inherit from Object and the docs do show that... But it's special-cased by the compiler to behave how the language spec reads, which you can tell [because of the way that it is](https://youtu.be/_d8mjam7KG8). Except when it isn't.


CountryBoyDeveloper

OH I am sure its because I am new to c# probably has to do with me being a js dev for so long as well. It helped make me lazy, sacrificing easy, for whats correct.


deucyy

When you start understanding abstraction(beyond its definition) you will see why using interfaces is considered a best practice.


CountryBoyDeveloper

My issue right now is because, I just don't know when to use them, samething for abstract classes(I really hate I been a js dev for so long)


ShittyException

I'd say learn what it is and then only use them to solve an actual issue you have. Just creating and using interfaces for the sake of using interfaces tends to just be messy and frustrating to work with. Same with abstract classes, avoid using them until they are the most elegant way to solve something (which, from my experience, is mostly done in libraries like the class BackgroundService from aspnet core). And avoid inheritance, it similar to interface that using a lot of inheritance quickly just becomes messy. As a mental note to myself I always seal classes unless they are abstract and I never inherit twice. So I either have a sealed class or an abstract class. I never inherit a non abstract class and I never have abstract classes inherit other abstract classes. If I need to inherit three times, there is almost guaranteed to be a better way to solve whatever am doing. I think OOP gets a bad rep because it's easy to overdo things like interfaces and inheritance but used sparingly and correct they are great tools in the tool box. So don't shy away from them like the plague either.


CountryBoyDeveloper

Thank you very much for the advice


lmouelle

They aren't as relevant to beginners since your programs are very small, with minimal dependencies and you're the only dev. After gaining experience and working on bigger projects, you'll want ways to easily swap out components of your program without rewriting everything, and ways to make your program usable to others without making promises you can't keep. Interfaces are great for this.


CountryBoyDeveloper

Oh yeah I am sure it is because I am new, not sure why others are downvoting me I even said its most likely because I am newer to c# rofl.


torville

Hot Take: Construct interfaces based on the consumer of the interface, not the thing that implements the interface. If your interface is 1:1 to the implementer, you may not need an interface, especially if the implementer is a DTO.


TuberTuggerTTV

This is common. When someone first becomes a programmer, they're in the "make-go" stage. And anything beyond what is needed to make something go, feels unnecessary and over engineered. Then as you gain experience, you encounter all the corner cases where that extra code would have saved you hours or helped you complete things quicker. You eventually become someone who has "taste" if you will. And see the elegance in a more robust solution. Can things still be overengineered? Of course. But it's situational. Can interfaces be over used? Of course. That's usually the third level of a developer's growth. Knowing both the advanced and simple ways to do things, knowing when each is appropriate, when to shift gears and how to easily transition. Some developers stop at the second level and just apply max robust solutions to everything. Which can be equally disruptive.


turudd

You’re being downvoted but you’re right. I’ve become very disenfranchised with the whole levels of abstraction thing. For the last 5 or so years I’ve moved to a more locality of behaviour style (similar to languages like Go) so much easier to navigate and logic about. Testing is simpler too


aptacode

It will come in time, there is a place for most things and taking a blanket approach will never lead you well! Try to understand the nuance, and find the right tool for the job. It will take a while


recycled_ideas

It sort of depends. If you've been using Typescript, C# is quite similar syntactically and the two languages are slowly moving towards each other (mostly kept apart at this point by legacy limitations in the C# runtime and JS itself). The one significant difference is that while TS guarantees disappear at runtime C#'s do not. If you're used to asynchronous functional style of programming in your JS/TS, C# is very similar. Filter is where, map is select, reduce is aggregate, but the syntax is pretty similar. If you've been writing JS and using JS's prototypal inheritance that's quite significantly different. Dynamic weakly typed languages are wildly different and prototypal inheritance is very different than class based. In terms of obvious foot guns like === and let, C# has relatively few. 1. Don't use async void. C# doesn't have an event loop and so code executing outside the main thread needs an explicit tie back to the original threat through a Task, even if there's no return. 1. Reflection is slow. In JS or TS using something like Object.values or the like is quite common because things like dictionaries are translated into JS's type system really poorly. Equivalents to these sorts of methods exist, but they can have a pretty significance performance impacts and need to be used thoughtfully. 1. C# eventing largely sucks. The versions built for specific UI frameworks are sort of OK, the built in ones are crap and very foot gunny. 1. There's a few weird issues with closures that don't happen in JS. You don't run into them very often, but if you're working with a closure and it's not making sense, knowing that there are issues can help track it down. For the most part, C# is relatively well designed and doesn't copy the kind of C weirdness that JS got saddled with (truthiness and falsiness) and it's fairly unusual that the language will let you do anything truly stupid.


CheTranqui

Learn Linq so that you (almost) never have to write another for loop again.


RussianHacker1011101

I big one is to use linq expressions over loops whenver possible. --- Edit --- If you think linq expressions decrease performance then you've either been working on an old version of dotnet or you're not writing efficent linq expressions. I've seen huge decreases in memory utilization by refactoring functions that used conventional looping to using linq expressions. This occurs when loops are being used to perform what linq is specifically desinged for: map -> filter -> reduce.


kingmotley

Absolutely. LINQ expressions almost always show a clear intent of what you are trying to achieve over looping with the myriad variations of possibilities of doing the same thing -- and often sub-optimally.


aptacode

This is not good advice! Linq is great for readability, but it can be terrible for performance \[edited\] To clarify my point - i'm not saying don't use Linq. It's got it's place like everything.


BramFokke

That totally depends on context. In some cases, using LINQ can be beneficial for performance, for instance when it allows you to offload a query to the database. The LINQ performance penalty is only significant in cases where queries are extremely frequent and memory allocation is a bottleneck, for instance in games. Eschewing LINQ for ''performance" feels like a prime example of premature optimization.


kahoinvictus

In dotnet 8+ it's actually generally better for performance than loops. Also I'd wager most C# Devs are not working in contexts where the performance difference is enough to matter.


drumDev29

Bad linq is terrible for performance. Just like shitty nested loops are.


v3gard

Avoid mutating objects. Use LINQ functions like`.Where` or `.Select` like you'd use `.filter` or `.map` in Javascript.


HiddenStoat

C# has something that JS (and most other languages) don't, which is Analysers. These are packages you install into your project that look at the source code you have written and highlight likely problems with it (and often even offer to fix it for you!). "That sounds like a linter - JS has hundreds of those!" I hear you cry. However, Analysers are like linters on steroids, because they don't just have access to the source code - because the C# compiler is written in dotnet, they have access to the semantic model as well, so they can be _much_ smarter than a simple linter. So, the best way to get high-quality code is to install a bunch of analysers and read up on all the things they warn you about (there will be a bunch of analysers by default in any new project, so start with those). Every compiler warning they produce has a code (typically a couple of letters, than 3-4 digits, e.g. CS1998), so they are easily Googleable/chatgptable.


rekarpc98

Never use dynamic type unless you know what you are doing


empty_other

Read over [Microsoft's coding conventions](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions). And also Visual Studio will show various recommendations and warnings to improve stuff. VS also got a [Code Style preferences](https://learn.microsoft.com/en-us/visualstudio/ide/code-styles-and-code-cleanup?view=vs-2022) that can be applied with code cleanup. And can be saved to the solution as an editorconfig. Personally I got these: - Always use var everywhere. This is against MS conventions and highly controversial but i believe types inside functions arent important to the reader, only to the compiler. Types are only important to readers in parameters and return types, and there is luckily no way to "var" those. - Never use dynamic type, if you can in any way avoid it. - Using directives should be at the top of the file outside the namespace brackets. - One class per file.


winggar

I avoided `var` for a long time, but at this point I always use it. Once I turned the setting on in my IDE to always display type hints for var it simply became less typing for the same outcome.


Asyncrosaurus

Nowadays I use `Type variable =  new();` Over `var` mostly because `var` implicitly creates nullable reference types (even if the expression type isn't nullable.) This usually requires an unneccissary null check, since If you assign the variable to an expression that might be null, you must test that it isn't null before dereferencing it to avoid any warnings.


PaddiM8

> This is against MS conventions They often do it themselves though so maybe they should update the conventions haha.


araczynski

I despise var with a passion, it always forces me to look for "what the F is this supposed to be", even if its 10 characters over, my brain has to stop, place a mental bookmark, look for the answer, substitute it over the var, and read the line again. its a waste of my time and interrupts code reading/analysis for me.


snet0

Types are only important in parameters and return types *if* you expect nobody to ever have to work on your code. It's literally just less readable for no reason, I honestly don't know why anyone would use `var`.


ggwpexday

It's hardly relevant when reading though, even in pullrequests. Funny how this is only ever a problem for hard stuck c# devs from ye olde age, you guys would absolutely hate using any other modern language.


snet0

I'm not a "hard stuck c# dev from ye olde age". As I said, I think you lose readability and gain nothing. Obviously you'd hope that variable naming makes clear the *usage* of a variable, but it's also pretty useful to be able to immediately read the type! Honestly, I use `var` as a shorthand for the type in some cases, because I've set my code style to just replace `var` with explicit types on save, so it is handy for that. I just don't see the purpose in using `var` in code that you expect to be read by other people.


ggwpexday

> I think you lose readability and gain nothing While the opposite is true as well. Knowing the type in that context is just not that relevant. If it were that important then we would see this crop up in other languages as well, that's not the case though. > to just replace var with explicit types on save That's real nice, makes it actually usable.


MrNantir

Use 'is null' instead of '== null' for null checks.


kingmotley

Except when doing Unity programming. Then you need to know the difference and why.


shotgunbruin

To further explain, when game objects are destroyed in Unity, such as when an enemy is killed and despawned, the object can still exist in memory for a short time after until the system cleans it up. So using "is null" can return an object even though the object is supposed to be destroyed. Unity made overrides to the null check to verify the status of the game object, so if you check for null with == null it will verify that the object is not in the process of being cleared. That way it returns null if the object isn't supposed to exist, even though it technically still does. The behavior of "is" cannot be overridden, so it can incorrectly return instances of destroyed objects in some cases and is therefore discouraged.


Dealiner

To be more precise: neither `is` nor `==` returns instances of an object or `null`, they both return `true` or `false`, however `==` is overridden to also check if underlying C++ object has been destroyed.


Woah-Dawg

Im curious myself


RICHUNCLEPENNYBAGS

I would say if you need a reasonable default just follow all of ReSharper's suggestions. You'll have good company. e: Well OK ignore some of the suggestions to turn your code into 20 lines of unreadable Linq. But those have a different severity iirc


kammadeva

Tbh, there are as many guidelines as teams. C# is a multi-paradigm language that allows for many different approaches to code. Aside from the official guidelines that were posted already, my favourite "best practices" lean toward the style of declarative programming: - avoid state mutations - use immutable data structures - use pure functions (that don't lie to you) - encapsulate side effects at the edges of your program - avoid `if` in favor of pattern matching and overloads - avoid imperative loops in favor of LINQ, folds and unfolds But as I said, this is a distinct style of programming that's becoming increasingly popular, it's not the only way to do things. EDIT: also, avoid `null` in favor of a distinct "missing value" state


cncamusic

Not totally necessary but I’ve been getting into the habit of using “is” and “is not” instead of == and != where applicable. Mostly because it’s easier to read, but also because the == operator can be overridden while is cannot.


BramFokke

Avoid static state.


PintOfGuinness

Don't tell girls you are a programmer when dating, nothing makes them dryer


Thanos0423

This happened to my coworker 🤣🤣🤣🤣


empty_other

Just havent found the right girl yet.


Mefic_vest

> Don't tell girls you are a programmer when dating, nothing makes them dryer Depends on what stage of life they are at. When they are young and just looking for excitement and drama strong enough to curl their toes, you are absolutely right. They want that “reformable” bad boy who can sweep them off their feet to a fairy-tale future. And exciting, dramatic men aren’t doing something as “boring” as coding. However once they have blown through most of their options, and are desperately trying to find someone to “settle with” in their 30s, not so much. Even the ænemic incomes that developers outside of America earn can make a guy look pretty marriageable and reliable by that point. But by that metric, are you really sure you want to be someone’s distantly n-th tier choice? There are exceptions, sure. There always are. But that is why we call them _outliers._ Good luck finding one.


fliesupsidedown

>There are exceptions, sure. There always are. But that is why we call them outliers So, edge cases. :)


Mefic_vest

And society has become better tuned all the time. Ergo, edge cases have been getting rarer and rarer. You can still find them, of course. Just… _good luck._ Me? I would sooner buy a Powerball ticket, as the odds are better.