4 ms·
There's no reason to program in C# if you already know C++.
by otabdeveloper4 5y ago
There's no reason to program in C# if you already know C++.
- ameliaquining 5y agoMemory safety? Garbage collection? Library ecosystem?
- nine_k 5y agoRAII is a kind of garbage collection, too. Longer-lived objects still need (trickier) manual deallocation.
- josephcsible 5y ago> RAII is a kind of garbage collection, too. No it isn't. With RAII, you can look where an object gets constructed and know exactly where it will be destructed. With garbage collection, you can't, and in fact there's no guarantee that it ever will be. Also, with garbage collection, you can save references to whatever you like, wherever you like, for as long as you like. With RAII, you need to make sure you don't create any dangling references or use any dangling pointers.
- ameliaquining 5y agoI meant tracing garbage collection. I'd say that something like 95% of allocations in real-world code can be done straightforwardly with RAII, or could be if the language supported it (and indeed gain maintainability benefits from being forced into an RAII-centric paradigm). But the remaining 5% is a real pain, and distributed over a wide variety of problems in a wide variety of domains. So tracing GC really does make life a lot easier, if you can afford it.
- pkolaczk 5y agoThe freedom to reference anything easily from any place is a double edge sword. I agree it makes 5% of hard issues go away, but on the flip side it makes the other 95% more complex. Tracing GC is a "goto" of memory management. You may argue goto is a good thing because it offers you freedom to jump from anywhere to anywhere and you're not tied to constraints enforced by loops and functions. We all know this is not the case. Similarly being able to make a reference from anywhere to anywhere leads to programs that are hard to reason about. We should optimize for readability not the ease of writing.
- ameliaquining 5y agoThere is no reason why you could not, in principle, have Rust-style compile-time borrow checking in a managed language. As an extreme example (that I have occasionally thought about doing though probably won't), you could fork TypeScript and add ownership and lifetime and inherited-mutability annotations to it, and have the compiler enforce single-ownership and shared-xor-mutable except in code that has specifically opted out of this. As with existing features of TypeScript's type system, this wouldn't affect the emitted code at all—heap allocations would still be freed nondeterministically by the tracing GC at runtime, not necessarily at the particular point in the program where they stop being used—but you'd get the maintainability benefits of not allowing unrestricted aliasing. (Since you wouldn't have destructors, you might need to use linear instead of affine types, to ensure that programmers can't forget to call a resource object's cleanup method when they're done with it. Alternatively, you could require https://github.com/tc39/proposal-explicit-resource-management https://github.com/tc39/proposal-explicit-resource-managemen... to be used, once that gets added to JavaScript.) Of course, if you design a runtime specifically to be targeted by such a language, more becomes possible. See https://without.boats/blog/revisiting-a-smaller-rust/ https://without.boats/blog/revisiting-a-smaller-rust/ for one sketch of what this might look like.
- tsimionescu 5y agoNo, with RAII you still need to design your program around who owns each object, and thus who should clean it up. You end up with borrowing, move semantics and others. With (Tracing/Copying) Garbage Collection, none of this exists. Not to mention, Copying GC also solves memory fragmentation, which C++ still suffers from unless you also design your allocations carefully around sizes of types.
- pkolaczk 5y ago> No, with RAII you still need to design your program around who owns each object, and thus who should clean it up With or without RAII you should design your program around who owns each object, unless you want to end up with unmaintainable mess leaking file descriptors, network sockets, native memory buffers or trying to access resources after closing them. Which is why Cassandra and Netty implement their own reference counting. > Not to mention, Copying GC also solves memory fragmentation Not really. It only moves the problem elsewhere so it doesn't look like fragmentation. Compacting GC needs additional memory to have a room to allocate from, and that amount of memory is substantial unless you want to do more GC than any useful work. Also it is not free from fragmentation most of the time - the heap is defragmented only at the moment right after compaction. As soon as your program logically frees a memory region (by dropping a path to it), you have temporary fragmentation until the next GC cycle, because that region is not available for allocation immediately. And there is internal fragmentation caused by object headers needed to store marking flags for GC - which can consume a huge amount of memory if your data is divided into tiny chunks. > which C++ still suffers from unless you also design your allocations carefully around sizes of types Modern allocators split allocations into size buckets automatically.
- nine_k 5y agoFortunately, with GC, you can avoid thinking about many small objects you constantly allocate along the way. Most of them will get collected the next GC run as a young generation going out of function / block scope. Some of them will travel down the call graph and may end up long-living, then eventually collected. But I agree: for anything that you want to deallocate deterministically, or at least soon enough, you need to track ownership, and care about the lifetimes. Such objects are relatively few, though.
- jolux 5y agoOther than memory safety, simplicity, dependency management and build tooling, the .NET standard libraries, the open source library ecosystem, and so on...
- ARandomerDude 5y agoAll right, but apart from the sanitation, the medicine, education, wine, public order, irrigation, roads, a fresh water system, and public health, what have the Romans ever done for us?
- adev_ 5y ago> Other than memory safety, simplicity, dependency management and build tooling, the .NET standard libraries, the open source library ecosystem Not feeding the troll but outside memory safety, everything else you list exist in the C++ ecosystem with generally better alternative than in C#. And as soon as you do touch mmap , unsafe area or native code in C# you loose memory safety too anyway.
- tester34 5y ago>simplicity I didn't spent a lot of hours in C++ world, but it never felt simple - N compilers, N package managers, N ways to do everything
- adev_ 5y ago> I didn't spent a lot of hours in C++ world, but it never felt simple C++ is not simple. But presenting C# (or Java) as "simple" is equally hypocritical. The JVM or the CLR and their associated frameworks are monster of complexity, engineering and legacy that require close to an entire lifetime to be mastered entirely. C# (or Java) are "accessible", meaning a newbie devlopper can produce something halfway baked in these languages relatively quickly. And this is something you can not say about C++. But they are not in any way "simple".
- kaba0 5y ago
- xwolfi 5y agoThe other people you work with may not, #1 reason to choose a language despite my own knowledge of C++ :D