image
Archives

0

What would you change about C# if you could?


With nearly 60 answers to this question it's highly likely that your answer has already been posted. Please don't post an answer unless you have something new to say

Assume that your objectives are the same as for C#. I don't want an answer like "I'd write Python instead". I'm only interested in changes in the language itself - not in the standard library. Perhaps this would be interesting to discuss, but as it is shared between many languages it would be better to discuss this in another question instead.

Please post a single idea per answer; if you want to post several ideas, post several separate answers. Thanks!



- Archives
image

Archives

0

I would add support for:

  • Extension properties (if only to make fluent interfaces more fluent)
  • Extension operators

    listbox1 += "line"
    
  • Support for operators with generics (ie. specify that you don't really care about the type of the T, but that it has to support "addition" with the + operator)

    public class T Accumulate<T>(IEnumerable<T> values)
        where T : operator +
    {
        using (IEnumerator<T> enumerator = values.GetEnumerator())
        {
            if (!enumerator.MoveNext())
                return default(T);
            T result = enumerator.Current;
            while (enumerator.MoveNext())
                result += enumerator.Current; // this does not compile now
            return result;
        }
    }
    
  • More generic constraints, like "number" or "enum"

    public class Adder<T>
        where T : number
    


- Archives
image

Archives

0

The syntax of the switch statement. I would like it more "block oriented", and more like the rest of C#.

switch (foo) {
   case 1 {
      // ...
   }
   case 2, 3 {
      // ...
   }
   case 10..100 {
      // ...
   }
}


- Archives
image

Archives

0

Provide a macro system similar to Python's decorators, or maybe just make attributes more powerful. Using dynamic proxies or IL rewriting for simple AOP features like tracing or transactions is just overkill.



- Archives
image

Archives

0

Better support for type safety when dealing with reflection. As it is right now, I have to look things up using strings. Some libraries that use a lot of reflection, like Fluent NHibernate, solve this problem using expression trees, but it really shouldn't be necessary.

Why are my options things like:

foo(typeof(Bar).GetProperty("PropA"))

or

foo<Bar>(x => x.PropA)

Why not just:

foo(typeof(Bar.PropA))

Where typeof returns not a System.Type instance, but also MethodInfo or PropertyInfo depending on how it's used.



- Archives
image

Archives

0

I'd like to see the ability to pass properties by reference. Like

int.TryParse(some_numeric_string, out MyProperty)

It's already been done in VB, so it's definitely possible.



- Archives
image

Archives

0

Mine's a fairly simple one - i'd have preferred it if properties and methods were virtual by default.



- Archives
image

Archives

0

Erase from history C# 1.0 along with .NET 1.

I think the legacy of the non-generic past is the single biggest detriment to the consistency of the whole platform.



- Archives
image

Archives

0

Get rid of the C# 2.0 syntax for anonymous methods.

It's worse than the lambda syntax, and the only reason we need both is for backwards compatibility with C# 2.0 code.



- Archives
image

Archives

0

Make types shorter than int first-class members.

It's just crazy to have to cast the result of byte xor byte back to byte.



- Archives
image

Archives

0

Enable the creation of classes that have access to each other's private members, without letting the whole assembly see them.

Use case: basically pretty much every time you use "internal" on a field or a method. This usually means you require a backdoor which the client code should not have. But if the client code should not have that backdoor, why should the rest of your assembly? Limit it to just the one or two classes that actually need that backdoor.



- Archives
image

Archives

0

I would eliminate Null by default from language and framework. Null just when boxing on Nullable class.



- Archives
image

Archives

0

I've always wanted static interfaces for some reason. Maybe it's just me.



- Archives
image

Archives

0

The ability to write a ToString() extension method for enums.

So I can do something like:

public enum AmazingEnum
{
    amazingValue = 0
   ,reallyAmazingValue
   ,unbelievablyAmazingValue
}

public static class AmazingEnumExtension
{
    public static string ToString(this AmazingEnum amazingEnum)
    {
        switch(amazingEnum)
        {
         case AmazingEnum.amazingValue:
              return "This is amazing!";
         case AmazingEnum.reallyAmazingValue:
              return "This is REALLY amazing!";
         case AmazingEnum.unbelievablyAmazingValue:
              return "This is UNBELIEVABLY amazing!";
        }

        throw new ArgumentException("This is an invalid AmazingEnum", "amazingEnum");
    }
}

and call it like this:

string value = AmazingEnum.amazingValue.ToString();

As things work at the moment, the ToString() of System.Enum gets called due to how override resolution works.



- Archives
image

Archives

0

Remove static entirely, and replace with pure for methods and threadlocal for fields. Any data to be shared between threads should be passed as immutable data.



- Archives
image

Archives

0
  1. Improved support for defining local helper functions. Anonymous methods bring disproportionate runtime + code-size overhead, can't be generic, and recursive anonymous methods are very clumsy.

  2. Support for a generic type parameter constraint specifying constructor signature(s).

  3. Support for a generic type parameter constraint specifying method/property signature(s).

  4. Nullability should be handled consistently across reference and value types and disabled by default. "nullable string" and "string" should not be represented by the same type.

  5. A module system like SML's. The closest things C# has to approximating this are generics + interfaces and neither can unify multiple implementations of a set of related types and functions.

  6. Allow a default value to be specified for automatically generated property getters/setters

  7. Convenience features stolen from functional languages: pattern matching expression, let..in expression, etc.

  8. Extension properties, extension constructors.



- Archives
image

Archives

0

I want to be able to have lambda expressions in custom attributes. For example...

[SomeAttribute(p => some_code(p))]
public string SomeField;

For reasonable flexibility, custom attributes should be able to be generic, so that the lambda expression can be properly typed:

[SomeAttribute<string>(str => some_code(str))]
public string SomeField;

This should be pretty simple to implement in the CLR and the C# compiler, too. Just turn the lambda expression into a static method on a special compiler-generated static type that contains all these methods for all those lambda expressions in custom attributes. Then compile the custom attribute data to one that contains the metadata token for that method. The CLR would recognise that the parameter is of a delegate type and automatically turn the metadata token into a delegate by calling Delegate.CreateDelegate() when the custom attribute is requested.



- Archives
image

Archives

0

I would implement anonymous iterators.



- Archives
image

Archives

0

I would have designed out and ref parameters properly, not the hack that C# has now. In particular:

  • out should have been implemented just like the return value: the value should be copied into the out location when the method returns.

  • Inside the method body, assignments to an out parameter within the method should not modify a storage location outside the method (which was passed in by reference).

  • ref should have been implemented in such a way that it would be functionally equivalent to having two parameters: one in and one out.

  • This would enable out parameters to be contravariant just like the return type, and just like in parameters are covariant. Only ref would need to be invariant.



- Archives
image

Archives

0

Virtual methods could have been a lot more flexible. A derived type should be able to make a virtual method more general. In particular:

  • A virtual-method override should be able to specify a more general parameter type (a base class or an interface).

  • A virtual-method override should be able to specify a more specific return type (a subclass).

  • A virtual-method override should be able to loosen the constraints on its generic type parameters.

  • A virtual-method override should be able to broaden the accessibility modifier.

The only problem with this is a subtle form of brittle base class which would hardly occur in practice. Beside that, none of these would cause any trouble with compile-time type safety, nor any accessibility loopholes.



- Archives
image

Archives

0

System.ValueType, System.Enum and System.Delegate would be a lot more useful if they worked everywhere where you can reasonably expect them to work. Currently they do not work:



- Archives
image

Archives

0

i'd have preferred if LINQ to SQL is compatible with the others database types (Oracle,MySQL,PostgreSQL...)



- Archives
image

Archives

0

Allow default value setting in auto-properties, and the addition of the readonly keyword. eg

public int MyProperty { get; private readonly set = 100; }


- Archives
image

Archives

0

Introduce an abstract/interface .ctor, which would require derived types to implement a .ctor with matching arguments. This would solve the limitations of the new() constraint in generics. I'd also make the constructor named this, or self for consistency.

In addition, constructors could be made virtual to mean they are replicated in subclasses (unless overridden). So that you don't need to bother manually adding those constructors who just pass their arguments to the base class anyway. (and do nothing else).

Delayed construction would be useful here, in the event you wish to perform some calculations on the parameters before calling the base constructor - although this can be a dangerous weapon if used incorrectly.



- Archives
image

Archives

0

It'd be nice if unassigned event handlers wouldn't throw a NullReferenceException and had a built-in thread-safe implementation for calling. You should be able to do this:

PropertyChanged(this, new PropertyChangedEventArgs("Foo"));

instead of having to do this:

PropertyChangedEventHandler h = PropertyChanged;
if (h != null)
{
   h(this, new PropertyChangedEventArgs("Foo"));
}

I really can't think of any risk a change like this would introduce, other than code not being backward-compatible once it was added to the language.



- Archives
image

Archives

0

I would add

foreach(thing t in things)
{
//do stuff
}
else
{
//this only runs if there are no iterations above
}

probably could work with other loop types too



- Archives
image

Archives

0

I would restrict var to enumerable query results (probably would change the keyword to query at the same time), create a contextual keyword called anon to deal with anonymous types outside of query results, and then make the class name optional on the right side in an initialization statement.

It would cut out utter crap like

var mystring = "lol"; // not permissable, lazy bum
var randomObject = ThisFunctionNameMeansNothing(); // get the freak out

While still cutting down on space produced by generics and long class names

MyRidiculouslyLongClassName<string, int, Foo> myClass = new();


- Archives
image

Archives

0

Get rid of the var keyword.

Allow fall-through cases in switch() without having to jump through hoops.

I'd love a version that's less entangled with the framework that could be used to generate native code. C# is a lot like Delphi (thanks, Anders!) which used the Borland C++ compiler back-end. There's no reason C# couldn't do the same with MSVC.

Support for inline assembly. Just because I'm crazy like that.

A neat trick would be to build something that compiles C# into C++. You'd get to keep succinct syntax, a great object model, good exception handling, etc. I know there's no 1:1 correspondence between the two languages on many points, but it's possible. Yeah, I'll get right on that (not).



- Archives
image

Archives

0

Get rid of public static class.

There's no reason to pack everything inside classes when the functions can do just as well as free functions in namespaces.



- Archives
image

Archives

0

Smarter if statements ie:

object foo = GetAnObject();
if(foo is string) 
    Console.WriteLine(foo.ToUpper());//foo is typed as string
else if(foo is int)
    Console.WriteLine(foo + 2);//foo is int


- Archives
image

Archives

0

Language support for property change notification (INotifyPropertyChanged):

public observable int Foo { get; set; }

The code above would have the same meaning as this:

private int _foo;
public int Foo
{
    get { return _foo; }
    set
    {
        _foo = value;
        OnPropertyChanged("Foo");
    }
}

(this was suggested on uservoice for WPF bindings, but it would be useful in other areas too)



- Archives
image

Archives

0

Numeric literal suffixes for all numeric types

Currently the following suffixes exist :

  • 1 (no suffix) : int or double (based on decimal separator)
  • 1U : uint
  • 1L : long
  • 1UL : ulong
  • 1f : float
  • 1d : double
  • 1m : decimal

For other numeric types, you have to cast explicitly :

  • (byte)1
  • (sbyte)1
  • (short)1
  • (ushort)1

I'd like to have the following suffixes added :

  • 1B : byte
  • 1SB : sbyte
  • 1S : short
  • 1US : ushort

And since there is a BigInteger type in 4.0, it would be nice to have a suffix for it too (perhaps use lowercase b for byte, and uppercase B for BigInteger)



- Archives
image

Archives

0

Enums that actually represent a contiguous set of numbers should be permitted for array indexes. Sure, you can easily cast them but that doesn't let the compiler protect you from mistakes. This would also apply to bools.



- Archives
image

Archives

0

I would add a special Haskell-like syntax for Tuples.

So that instead of this:

public static Tuple<int, int> Divide(int a, int b) {
  return Tuple.Create(a / b, a % b);
}

var t = Divide(16, 3);
var division = t.Item1;
var remainder = t.Item2;

you could write this:

public static (int, int) Divide(int a, int b) {
  return (a / b, a % b);
}

var (division, remainder) = Divide(16, 3);


- Archives
image

Archives

0

I would want a placeholder syntax (_) for lambda expressions (like in Scala).

Consider the following code:

var namesOfAdultUsers = users.Where(c => c.Age > 18).Select(c => c.Name);

With placeholder syntax, this could be written more succinctly as follows:

var namesOfAdultUsers = users.Where(_.Age > 18).Select(_.Name);


- Archives
image

Archives

0

Having previously worked in C++ before C#, I really miss templates. Generics are close, but you can't specify non-types as a generic parameter. C++ template parameters allow typenames and primitives (int, enum, etc.). C++ templates also allow defining specializations. This allows for a wide variety of compile-time specialization. This is entirely useful when portability of generics is not a requirement.



- Archives
image

Archives

0

Enforcing that Linux and OS X are officially supported platforms.

Currently it is vendor-lock in.



- Archives
image

Archives

0

Embed Reactive Extensions

While I'm still coming up to speed on this technology, it seems to me that it has some great implications for improving UI -> business object decoupling (thereby reducing memory 'leaks' from forever-referenced objects) and for helping with M-V-VM design.

See Reactive Extensions for details.



- Archives
image

Archives

0

It'll be nice if type inference is extended to collection initializers. So that instead of writing the code like following:

var dict = new Dictionary<int, List<string>> {
  {1, new List<string> {"ek", "one", "ooga"}},
  {2, new List<string> {"don", "two", "bira"}}
};

I could just write:

var dict = new Dictionary {
  {1, new List {"ek", "one", "ooga"}},
  {2, new List {"don", "two", "bira"}}
}


- Archives
image

Archives

0

Not sure if someone put something about automatic casting:

int age = 70;
var foo = "John Lennon would be " + age + " years old";
Console.WriteLine(foo);

//---- output
John Lennon would be 70 years old


- Archives
image

Archives

0

I'd get rid of the syntax litter like {} and ;. And var (which makes a C# programmer a VB.NET programmer)



- Archives
image

Archives

0

I would add Duck-Typing. Think of it as implicit interfaces. If an object implements the set of methods that compose an interface it is considered to implement that interface, even if the class does not explicitly name it.



- Archives
image

Archives

0

Not so much a Problem with C# but with the BCL: Wipe out all non-generic collections.

Goodbye ArrayList, Hello List<Object> if you really need a 'non-generic' collection, at least be explicit about it.

Have TableRowCollection actually return TableRow instead of Object.

IEnumerable? Was nice knowing you, now go away.



- Archives
image

Archives

0

Case-sensitivity.

I'd make C# autocorrect case like VB .NET does, so that whether you type in all caps or all lower-case or a mixture, your code comes out in the correct case once you move off the line.

It vexes me greatly when I type the name of a class, but I don't happen to capitalize it, and C# pretends it has no idea what I'm talking about.



- Archives
image

Archives

0

Some syntactic sugar for the long-winded type-check-and-cast:

if (obj is MyType)
{
    var o = (MyType) obj;
    <use o>

e.g.

if ((var o = obj as MyType) != null)
{
    <use o>

or something a bit less ugly and more thought-through.

Better still, perhaps some special support for polymorphic extension methods. Code like the above is often the result of writing an extension method that would really have been a virtual method with overrides had it been implemented in the original class.



- Archives
image

Archives

0

One thing that I miss from my C++ background is const correctness. i.e. do not allow constant objects to be changed.



- Archives
image

Archives

0

I want indexers not to limit modification. like this:

...
// MyList<T>
public this[int index]
{
get{/*do something to return value*/}
set{/*do something to set value*/}
}
...

so:

MyList<MyPersonClass> lst = new MyList<MyPersonClass>();
lst.Add(SomePeople);
lst.Add(SomeOtherPeople);
lst[0].name = "Fred";    // error
lst[1].last = "McKenny"; // error


- Archives
image

Archives

0

Sometimes I miss friend class and functions. They are quite powerful in some scenarios.
Apart from that they can also help in unit testing private methods of a class.



- Archives
image

Archives

0

Add some helpful syntatic sugar for the decorator pattern (i.e. composition not inheritance)

interface IWindow {
    public void Draw();
    public void Close();
    ... more methods ...
} 
sealed class SimpleWindow: IWindow {
    public void Draw() {/* draw window */}
    ... more methods ...
}
//extending this to add a scoll bar
sealed class ScrollBarDecorator : IWindow {
    private IWindow _component; //component class that has the basic implementation

    public VerticalScrollBarDecorator (IWindow decoratedWindow) {
        _component = decoratedWindow;
    }

    //"override" the behaviour we want to change/extend (one line)
    public void IWindow.Draw() {
        DrawScrollBar();
        _component.Draw();        
    }

    //then type lots (potentially pages) of boilerplate code to forward the rest of the methods straight to the underlying component
    public void IWindow.Close() {
        _component.Close();        
    }
    ... more methods ...
}

Unpleasant. Most people won't bother or will find any way to avoid this (i.e. damaging their class structures, twisting their code, bloating type hierarchies) - whereas, if we had a bit of syntatic sugar for this:

sealed class ScrollBarDecorator : IWindow {
    //note the new keyword "decorates"
    decorates private IWindow _component;

    public VerticalScrollBarDecorator (IWindow decoratedWindow) {
        _component = decoratedWindow;
    }

    //"override" just the behaviour we want to change/extend
    public void IWindow.Draw() {
        DrawScrollBar();
        _component.Draw();      
    }
 }

Finished. The boiler plate code to implement IWindow, delegating all the calls to _component would be implied/generated by the compiler. Far more coders would use this pattern if it were this simple to type.



- Archives
image

Archives

0

I would make the language and also the common language runtime have yet more static typing with; kinds, monads and type-classes. It would allow all the generic constraints suggested above, on both methods and properties.

This discussion on channel9 shines some light on why this would be great in a multi-core world. Principally it would allow you to encapsulate state changes into the type system, allowing for greater library optimisation and improvements.



- Archives
image

Archives

0

I'd change the name - C# - Google ignores that # character when you search for language-related things so you get unsolicited results for C/C++ stuff.



- Archives
image

Archives

0

I would like to be able to add white space to values inside of enums. I know this seems minor but it actually comes up a lot.



- Archives
image

Archives

0

"raise" keyword for events

I'm tired of writing small methods just to trigger events thread-safely.



- Archives
image

Archives

0

Eliminate "ref" and "out" parameters

Surely there has to be a better way, I cringe every time I has to use a BCL method with ref parameters (like TryGet)



- Archives
image

Archives

0

In C#/.NET, there is no consistent support for deep equality. Most Equals() and operator==() implementations in .NET merely do Object.ReferenceEquals(), but there are exceptions, such as String. As a result, you need to implement your own equality function for just about every class in the .NET library. Furthermore you need to memorize for each class which comparison function you need to use: operator==(), Equals() or MyOwnEqalityFunctionAsExtensionMethod().



- Archives
image

Archives

0

There is no consistent support for deep copying. Most classes in the .NET library don't have a Clone() function. As a result, it is for example impossible to provide a deep clone function for a generic List.



- Archives
image

Archives

0

First about this, is that I don't like the way this question is posed specifically the requirement of one answer for post, since that is a call for spamming.

So, I would leave all my answers in one post, and let people vote accordingly, and if they want specify the one they like or don't in the comments to this answer.

  1. I would go and remove everything that only has one use, since there is probably some other way of doing that without that change;

  2. Make the language more stable, so that it don't change as the versions of visual studio or .net change, that would do a lot for the language adoption, since it is what java always had, and java is the language of the seven lifes.

  3. Remove lambda expressions, since delegates are more general and do the same.

  4. Remove the var keyword, or add the requirement that you either use vars (dynamic types) or static types, since it is a mess to find both of them in the same function!

And thats all, folks...



- Archives
Cancel