Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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.

share|improve this question

closed as not constructive by ChrisF Oct 27 '11 at 20:41

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.If this question can be reworded to fit the rules in the help center, please edit the question.

    
Keyword new –  Nemanja Trifunovic Mar 3 '11 at 20:19
2  
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

13 Answers 13

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.

share|improve this answer
    
This is too great. –  acidzombie24 Jan 27 '11 at 4:47
1  
Not all ports of .NET support Generics. .NET Micro is an example. May not apply if CustomObjects will never move to this platform. –  makerofthings7 Jan 28 '11 at 16:23
2  
That's the advantage to not having a soul. –  CaffGeek Oct 27 '11 at 20:43

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.

share|improve this answer
    
Agreed, anonymous methods were great when we didn't have lambdas...now they're just redundant. –  Mike Brown Jan 28 '11 at 18:56
8  
There is one special feature of anonymous methods thats far better than lambda expressions .... their perfect name !! –  explorest Jan 28 '11 at 19:36

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>.

share|improve this answer
4  
... and Task is just a Task<Unit>. Reimplementing the library bits of the async CTP made me really wish for this... –  Jon Skeet Oct 27 '11 at 19:24

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.)

share|improve this answer
    
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<T> inherited from IReadableList<out T> and a non-generic IPemutable, it could support things like sorting, but arrays support it more easily. –  supercat Mar 12 at 6:52

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

share|improve this answer
6  
Not to mention the huge performance penalty under the 64-bit JIT </snark>. –  Jesse C. Slicer Jan 28 '11 at 19:43
6  
An empty statement has a performance penalty? Why is that? –  qes Oct 27 '11 at 20:07

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.)

share|improve this answer
1  
for (int i=0;i<ceiling;i++) –  Mike Brown Jan 28 '11 at 19:02
1  
a = i++; is good... a = ++i; is annoying. –  makerofthings7 Jan 28 '11 at 19:11
12  
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
6  
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 5 '11 at 13:26
3  
@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 1 '11 at 15:50

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.)

share|improve this answer
    
I'd perhaps lean to identifying literals that imply a value that cannot be represented as a double/float precisely... –  ShuggyCoUk Nov 1 '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" 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 6 '13 at 3: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 6 '13 at 8: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 at 23:02

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.

share|improve this answer

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>
share|improve this answer
3  
I like the Predicate<T> 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

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

share|improve this answer

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.

share|improve this answer
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 ;) –  Mike 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 at 6:49

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.

share|improve this answer
    
Winforms seems much more stable, faster, and less buggy than WPF... –  Pacerier Aug 29 at 23:04

asmx Web Services

I think they are quite obsolete with WCF nowadays.

share|improve this answer
6  
Yeah, but sometimes much easier to grok . . . –  Wyatt Barnett Jun 3 '11 at 21:45

Not the answer you're looking for? Browse other questions tagged or ask your own question.