18

Any product or framework evolves. Mainly it's done to catch up the needs of it's users, leverage new computing powers and simply make it better. Sometimes the primary design goal also changes with the product. C# or .net framework is no exception. As we see, the present day 4th version is very much different comparing with the first one. But thing comes as a barricade to this evolution- backward compatibility.

In most of frameworks/products there are features would have been cut off if there was no need to support backward compatibility. According to you, what are these features in C#/.net?

Please mention one feature per answer.

Maniero
  • 10,826
  • 14
  • 80
  • 133
Gulshan
  • 9,402
  • 10
  • 58
  • 89
  • 4
    The question is clearly not constructive according to the guidelines, and clearly constructive based on the fantastic answers. Voting to re-open. – psr Oct 27 '11 at 23:11
  • 1
    shame it closed, still maybe Eric will blog this instead of answering here? – jk. Oct 28 '11 at 14:29
  • [Keyword new](http://programmers.stackexchange.com/questions/47678/purpose-of-new-keyword/) – Nemanja Trifunovic Mar 03 '11 at 20:19

13 Answers13

35

Anonymous methods. I think everyone agrees that the anonymous method syntax chosen for C# 2.0 is chunky and clunky compared to the lambda syntax we added to C# 3.0. It is deeply unfortunate to have two almost-identical syntaxes to do the same thing.

Eric Lippert
  • 45,799
  • 22
  • 87
  • 126
  • 1
    Agreed, anonymous methods were great when we didn't have lambdas...now they're just redundant. – Michael Brown Jan 28 '11 at 18:56
  • 9
    There is one special feature of anonymous methods thats far better than lambda expressions .... their perfect name !! – explorest Jan 28 '11 at 19:36
  • 1
    At this point, I don't even remember the syntax for an anonymous method in C#. I'd have to look it up if for some bizarre reason I needed to use one instead of a lambda. – Kyralessa Oct 10 '19 at 14:07
33

I'd get rid of the Non-generic collections. They are an abomination...and there are too many cases where I'm using linq and have to do something like

var customObjects = container.CustomObjects.Cast<CustomObject>();

Every time I have to do that, a small part of my soul dies.

Michael Brown
  • 21,684
  • 3
  • 46
  • 83
29

void as a type. Why on earth is "void" a type? It has no instances, it has no values, you can't use it as a generic type argument, formal parameter type, local type, field type or property type. It has no meaning as a type; rather, it is a fact about what effect a method call has on the stack of the virtual machine. But the virtual machine is just that: a virtual machine. The real machine will put the returned value in a register (typically EAX on x86) and not affect the stack at all! Void as a type is just a bad idea all around.

Worse: when used in a pointer type as in void* it means something completely different than what it means when used as a return type. Now it means "a pointer to a storage location of unknown type", which has nothing whatsoever to do with its meaning as "a method that doesn't return any value."

We can replace void* as a pointer type with IntPtr. (And void** with IntPtr* and so on.) We can replace void as a return type with "Unit", a type that has a single value, namely, null. An implementation of the CLR could then decide that a unit-typed function call could optimize its usage of registers or stacks appropriately, knowing that the null that is being "returned" can be safely ignored.

In such a world you no longer need separate Func<A, R> and Action<T> delegates. Action<T> is just Func<T, Unit>.

Eric Lippert
  • 45,799
  • 22
  • 87
  • 126
  • 4
    ... and `Task` is just a `Task`. Reimplementing the library bits of the async CTP made me really wish for this... – Jon Skeet Oct 27 '11 at 19:24
24

The empty statement ;. Error-prone, almost always a typo, and gives you no added meaning that is not already expressed by {}.

Eric Lippert
  • 45,799
  • 22
  • 87
  • 126
22

Unsafe covariance on arrays of reference type. With typesafe covariance on IEnumerable<T>, at least some of the need for array covariance has gone away. (If we had a covariant read-only list interface then we wouldn't need it at all.)

Eric Lippert
  • 45,799
  • 22
  • 87
  • 126
  • I was absolutely going to write this down when I saw the question title -- you beat me to it :( – Chris Smith Jan 28 '11 at 16:24
  • 1
    The ability to receive a covariant array reference and safely write to the array *references that were read from it* is useful. If like `IList` inherited from `IReadableList` and a non-generic `IPemutable`, it could support things like sorting, but arrays support it more easily. – supercat Mar 12 '14 at 06:52
14

The unary plus operator. Least useful operator of all time. If we didn't have to keep it for backwards compat, I'd take it out in a heartbeat. Who uses this thing, anyone?

(Clarification: The unary plus operator +x is not the preincrement operator ++x, not the postincrement operator x++ and not the binary addition operator x+y.)

Eric Lippert
  • 45,799
  • 22
  • 87
  • 126
  • 1
    for (int i=0;i – Michael Brown Jan 28 '11 at 19:02
  • 1
    `a = i++;` is good... `a = ++i;` is annoying. – makerofthings7 Jan 28 '11 at 19:11
  • 13
    He's not talking about the preincrement and postincrement operators: he's talking about the unary plus, the opposite of the negative sign on a number: `+1 == 1`. It's pretty darn close to a no-op. – Jesse C. Slicer Jan 28 '11 at 19:31
  • @makerofthings7 It's worth warning new developers that there is a difference between `i++` and `++i` in an expression. Sometimes there can be a performance difference too: http://www.codeproject.com/KB/cs/FastLessCSharpIteration.aspx – Thomas Bratt Feb 05 '11 at 13:20
  • 9
    It's not just about the effect on the machine readable output, it can improve the look of code for humans: `if(a == +1 || a == -1){...}`. – Thomas Bratt Feb 05 '11 at 13:26
  • I suspect the value to the user in that situation in no way justifies what I would imagine is an utter PITA at lexing – ShuggyCoUk Nov 01 '11 at 15:44
  • 5
    @ShuggyCoUK: What is particularly bizarre about it is that it is *overloadable*. Because that happens a lot. You know, how you're writing some JavaScript and you think *man, I wish JS allowed me to make user-defined unary plus operator semantics like C# does*. – Eric Lippert Nov 01 '11 at 15:50
  • 2
    @Eric I did not realise it was overloadable. wow you could do some nasty obfuscation with that :) – ShuggyCoUk Nov 01 '11 at 16:08
  • Ahh...that reminds me of the days of mushing when you could create a door on yourself named Look and anyone who tried to look at you would inadvertently go through that door. I made a voodoo necklace that would collect the shrunken heads of anyone who looked at me. – Michael Brown Feb 21 '13 at 15:09
12

Defaulting numeric literals to double

For most business apps, decimal is more appropriate anyway... or maybe it would be better to just remove the idea of a default, and force developer to actually make the choice.

(That "remove the default" would be appropriate for some other things, too. For example, I've given up trying to persuade everyone that classes should be sealed by default, but I suspect it's easier to persuade people that they should think about whether their new class should be sealed or not, and make it explicit.)

Jon Skeet
  • 3,386
  • 7
  • 32
  • 27
  • I'd perhaps lean to identifying literals that imply a value that cannot be represented as a double/float precisely... – ShuggyCoUk Nov 01 '11 at 16:10
  • If they're into Java - refer them to the sacred texts by Joshua Bloch "design or document for inheritance or else prohibit it" http://martinfowler.com/bliki/DesignedInheritance.html IIRC kotlin does seal classes by default, so the industry is moving into a better direction in this respect. – Elazar Leibovich Aug 29 '12 at 18:48
  • Why should classes be sealed? – James Jan 06 '13 at 03:34
  • @James: For exactly the reasons Josh gives. Designing a class which enables inheritance in a sensible, consistent way takes time - and doing so without knowing how inheritance is going to be used is even worse. – Jon Skeet Jan 06 '13 at 08:46
  • @JonSkeet, As long as all the methods are sealed by default, what's the harm of allowing inheritance? Why do we need to seal up the entire class when the methods are already sealed up? – Pacerier Aug 29 '14 at 23:02
  • 1
    @Pacerier: Think about immutability, for example. A non-sealed class can't claim to be immutable, as subclasses can introduce mutability. – Jon Skeet Aug 30 '14 at 07:17
  • @JonSkeet If all fields/properties are readonly/get only, and the class only exposes those, wouldn't that make it immutable regardless of whatever a subtype did? – Asad Saeeduddin Aug 23 '15 at 23:32
  • @Asad: No. If a subclass allows mutation of its own state, you lose a lot of the benefits of true immutability - you can't reasonably share objects between threads, cache them etc... because the changes via subclass state may be important. – Jon Skeet Aug 24 '15 at 05:51
7

This is more a guideline than a feature, but I think it's important because it's already too much ingrained in people's minds as the canonical and best solution:

The official pattern to implement IDisposable.

It's cumbersome and there're better ways.

Jordão
  • 651
  • 6
  • 7
6

I know there are big differences between the various timer classes. But couldn't we get rid of one or two of them, anyway?

nikie
  • 6,303
  • 4
  • 36
  • 39
4

Methods and types of Array and List<T> that became obsolete with Linq, for example:

  • Array.TrueForAll can be replaced with Enumerable.All
  • Array.FindAll can be replaced with Enumerable.Where
  • List<T>.ConvertAll can be replaced with Enumerable.Select
  • Predicate<T> can be replaced with Func<T, bool>
  • Converter<T,R> can be replaced with Func<T, R>
  • IComparer<T> really should be a delegate Func<T, T, int>
nikie
  • 6,303
  • 4
  • 36
  • 39
  • 3
    I like the `Predicate` because it captures the intend on how the function is used and saves a tiny bit of typing. – Zebi Jun 19 '11 at 15:41
2

Non-generic Delegates Like non-generic collections, non-generic delegates are useless now that we have Func and Action series. And I would have cut off the variants at three parameters. If you have more than three parameters, make a structure and use that as the single parameter. Declaring a specific delegate for event handling is not very DRY.

Michael Brown
  • 21,684
  • 3
  • 46
  • 83
  • 3
    How would you define a delegate to a method that takes a ref int with Action or Func? How would you define a *combinator* with Func? That is, there's no way to say "delegate D D(D d);" with Func. – Eric Lippert Jan 28 '11 at 20:38
  • 2
    hmmm...I stand corrected. That's why I leave the job of creating the tools I use in your capable hands ;) – Michael Brown Jan 28 '11 at 21:02
  • @EricLippert: I'd like to see a special delegates class which would through CLR magic contain delegates of "every" arity and combination of value/reference parameters [searching for a delegate in the magic class with a suitably-formatted name would create the type], and have all delegates of proper signature inherit from that. Code which wants a particular delegate would still require an exact type, but code which wants a particular signature could use the magic name. – supercat Mar 12 '14 at 06:49
-1

asmx Web Services

I think they are quite obsolete with WCF nowadays.

fretje
  • 310
  • 1
  • 10
-2

Winforms
It would be nice not to have to navigate between two desktop platforms. WPF is where things are going, so its frustrating to have a full on platform level redundancy.

Morgan Herlocker
  • 12,722
  • 8
  • 47
  • 78
  • Winforms seems much more stable, faster, and less buggy than WPF... – Pacerier Aug 29 '14 at 23:04
  • When you just need to hack out a small desktop app, WPF is major overkill. – Kyralessa Mar 04 '15 at 15:32
  • It seems in between WPF has become pretty obsolete in favor of WinRT. However, to me it seems Winforms is more alive than WPF in business development. See also http://stackoverflow.com/questions/913417/will-windows-forms-be-deprecated-in-favor-of-wpf – Doc Brown Sep 27 '16 at 13:51