all copies are shallow by default |
You can do semi-deep copies (i.e. you create a new list that points to the same objects) easily, but it's hideous:
|
var list2 = list.Where(true).ToList();
|
While coding, I used a List of a List of tuple<int, int> which when outputted produces "( )" around the numbers by default.. Since it was a coding contest, my output had to match. So to get rid of the that extra garbage I had to do this |
Why not directly stringify the data the way you wanted?
|
list.Select(x => $"{x.Item1}|{x.Item2}")
|
Or, more efficiently, if more wordily, with a StringBuilder.
Wait until you try to deal with resources. One time I was writing a 5-10-kLOC program that dealt with many streams that I
needed to get disposed at precisely the right times, or the program was incorrect. I became so frustrated that I could never be sure whether I was writing the Dispose() implementations correctly or whether I had forgotten a using somewhere that I just scrapped it and rewrote it in C++. RAII is such a powerful tool, I'm still shocked so many people are willing to sacrifice it in favor of tracing garbage collection.
C# is very programmer-efficient as long as your logic can tolerate working approximately-right. You don't care too much
when or
how things happen, but
that they happen. If you need tight control over the behavior then it's unusable. I've seen the developers themselves say as much when asked about the details of how something worked (actually it was in an F# talk, but it's basically the same): "if you need fine control over this, you should use a different language."
C# is a nice language; its biggest issue is that it inherited OSO from java. (Objects for the sake of objects -- its unfriendly to procedural style or other ideas). |
Nah, you can write procedurally just fine. Just put your non-object functions in a static Utility class.
I think its biggest issue is that it has basically no code generation tools. For example, if you need a bunch of methods that are all the same but with a little change, you're basically screwed. You can't even include another file in the middle of your class, so that you can generate it from outside. IMO it desperate needs some kind of hygienic macro system. Or
something, because right now it has
nothing. Not counting serialization and such, the coolest trick I've seen it do is Dispose() all IDisposable objects via reflection, which at best puts it in the same position as default C++ behavior, only the programmer has to implement it manually.
Oh, and one other issue, its a little weird on unix (or was, not sure of current state). |
Mono works basically perfectly. The only issue I've had was when I needed to use SQLite, which is a bit of a pain because it needs a native module to work. Sometimes I've had desktop programs not start, but they were just curiosity tests so I didn't investigate what was going on or how difficult it would have been to fix them. The times I did care, they ran fine.
On the subject of distribution, one thing that does freak me out a bit is that nuget only downloads binary packages, not sources. A few days ago I removed all my packages from a particular project and added the sources to the solution because I wanted to make sure the project would still work ten years from now.