7

I was just dealing with strings, and I find myself annoyed that strings can be nullable. So, I have to have

if((teststring??string.Empty)==string.Empty)

all over the place. Would string? have been so hard for allowing nullability in the relatively few cases where it is needed (dbs, idiot user inputs, etc.). I also find myself irritated with having to export readonly interfaces in the cases where I want some form of const correctness. So, what C# language construct/decision annoys you?

EDIT: Thanks for the isnullorempty function, I hadn't seen that before! Still doesn't lessen my annoyance at it being nullable :D

Adam Lear
  • 38,111
  • 12
  • 81
  • 101
Steve
  • 11,763
  • 15
  • 70
  • 103

13 Answers13

28

Testing strings for Null or Empty is best done using:

if (string.IsNullOrEmpty(testString))
{
}
Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541
  • Since this question still gets a fair bit of traffic, it's worth noting that we now have `String.IsNullOrWhiteSpace`, too. – Yuck Dec 19 '11 at 18:48
21

Making string a reference type seems entirely reasonable to me.

It's a shame that one can't declare a variable/parameter/return type to be non-nullable though - e.g.

// Never returns null
public string! Foo()
{
}

Code contracts in .NET 4.0 will help with this, I believe - but it's a bit late to make it pervasive.

A while ago I wrote a blog entry on the mistakes of C#. To summarise that post:

C# 1:

  • Lack of separate getter/setter access for properties.
  • Lack of generics. Life would have been a lot sweeter with generics from the start.
  • Classes not being sealed by default.
  • Enums just being named numbers.
  • The "\x" character escape sequence.
  • Various things about the switch statement :)
  • Some odd overload resolution rules
  • The "lock" keyword, instead of "using" with a lock tocken.

C# 2:

  • Lack of partial methods (came in C# 3)
  • Lack of generic variance (coming in C# 4)
  • The System.Nullable class (not Nullable<T> - that's fine!)
  • InternalsVisibleTo requiring the whole public key for strongly signed assemblies instead of the public key token.

C# 3:

  • Lack of support for immutability - lots of changes improved opportunities for mutating types (automatic properties, object and collection initializers) but none of these really work for mutable types
  • Extension method discovery
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • nice list. I like the historical approach! – Steve Mar 13 '09 at 15:01
  • Much on the list is largely "it lacked the things that came in the next version"; yet we always survived until they were added... Some of them are genuine mistakes, though - I'll grant. – Marc Gravell Mar 13 '09 at 15:16
  • About "stuff in the next version" - some of these were just silly. Not allowing a private setter? Ick. That should have been an obvious goodness. Partial methods would have been a bit harder to spot the need. Generics was obviously required, but hard to define (i.e. more time needed). – Jon Skeet Mar 13 '09 at 15:35
  • 3
    The problem with adding generics later is that it affects the class lirbary *now*. The framework would have been a lot cleaner without the non-generic collections. Implementing IEnumerable without IEnumerable would be nice too... – Jon Skeet Mar 13 '09 at 15:36
7

Probably the biggest glaring hole in C# is, for me, enums.

Java enums are typesafe classes that you can give behaviour to, can implement interfaces and so on.

C#/.Net enums are just glorified ints with all the problems int constants have had going back to C and C++.

cletus
  • 616,129
  • 168
  • 910
  • 942
  • 1
    On the other hand, you can easily emulate complex Java enums by writing it as a class :p The only thing you would miss out on is the ability to `switch` on them. – JulianR Mar 14 '09 at 16:46
  • No theres more to it than that, like controlling how many instances there are of a notional value through serialization/deserialization and so on. – cletus Mar 14 '09 at 22:43
5

out and ref parameters

Michael Larionov
  • 470
  • 1
  • 5
  • 16
  • 1
    How would you handle it otherwise? – Beep beep Mar 13 '09 at 14:59
  • +1 Yes, this, 100%. I **hate** that `TryParse` uses output parameters. Would be lovely for `Int32.TryParse` to return a `ParseResult` object with `Exception` and `Value` properties. – Yuck Dec 19 '11 at 18:50
1

Expanding on Mitch's answer.

That is actually a CLR decision, not a C# one. C# has no control over the implementation details of the BCL's System.String class.

True C# could have special cased string in the compiler and said we'll do special null checks but that would have IMHO, been a bad decision. String.IsNullOrEmpty is an acceptable compromise.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
1

Enforcement of break in a non-empty case.

Verbosity of enums, especially in case statements. If I have switch (expr) and expr is an enum, I shouldn't be forced to fully qualify each enum in each case, unless there is a naming conflict.

plinth
  • 48,267
  • 11
  • 78
  • 120
1

Checked exceptions would have been great. I know a lot of people hate them from Java, but I think it's always enforced sanity checks, especially on I/O. I like most of the things that C# changed and/or added compared to Java, but I really would have liked them to have adopted checked exceptions. It's too late now (the .NET framework being changed to have them would break virtually every program out there) but I think it would have been better to have them.

Kevin Anderson
  • 6,850
  • 4
  • 32
  • 54
0

The way I have to implement properties from an interface in c# 3.0 even though they are exactly the same as the interface when I'm not changing default behaviour of auto properties.

e.g.

public interface MyInterface
{
   int MyProperty { get; set;}
}

public class MyClass : MyInterface
{
   public int MyProperty { get; set; }
}

public class MyClass2 : MyInterface
{
   public int MyProperty { get; set; }
}

public class MyClass3 : MyInterface
{
   public int MyProperty { get; set; }
}

EDIT: To address some of the comments on this. I'm not changing any default behaviour of my getter. I understand the difference between class and interface thankyou, my point is that my marking it with the interface I shouldn't have to have this property inside every implementing class unless I want to change the default behaviour of the getter or setter. Imagine 500 classes implement this interface?

Also the lack of Mixins..

Rob Stevenson-Leggett
  • 35,279
  • 21
  • 87
  • 141
  • 1
    How does this not make sense? Even though it's the same text, the meaning is very different. Interface is just saying "Property will have a getter". Class is saying "compiler, please create a private field and return it unmodified inside the getter". – Rex M Mar 13 '09 at 14:56
  • 1
    This decision makes sense to me. Without this, how would you differentiate if your interface ONLY required a property get, or only a property set? What if your class didn't use automatic properties (or was extended with logic in v2)? – Reed Copsey Mar 13 '09 at 14:56
  • Yes but what I'm saying is that once I've implemented the interface that property should be implemented behind the scenes unless I want to change it. I just find, particularly with data transfer objects that I'm writing the same code over and over. – Rob Stevenson-Leggett Mar 13 '09 at 15:04
  • 1
    I disagree. The interface is defining a contract - it shouldn't be *implicitly* generating code to fulfil the contract without anything in the class saying so. – Jon Skeet Mar 13 '09 at 15:06
  • I think you're firmly in the minority position in this one, Rob. – Marc Gravell Mar 13 '09 at 15:17
  • 1
    @Rob so how does the compiler implicitly implement int GetANumber(object foo)? Now your compiler arbitrarily determines a default method behavior and return value, which you forget to override and get a weird bug. Or get a compile error that you're not satisfying the contract. – Rex M Mar 13 '09 at 15:37
  • @Rex Only default property behaviour, I never mentioned methods. @Marc Looks that way :) – Rob Stevenson-Leggett Mar 15 '09 at 16:46
  • I also disagree. It sounds like you're pining for multiple inheritance. :-) – Christian Hayter Sep 15 '09 at 18:29
  • @Christian No I'm not. Nowhere do I mention multiple inheritance. I'm talking about C# specific autoproperties only. – Rob Stevenson-Leggett Sep 17 '09 at 11:49
0

Not allowing co/contra-variance or access rights changes when overriding base class or implementing interface methods:

public class A
{
    protected virtual Stream method()
    {
        //...stuff...
    }
}

public class B : A
{
    // compiler borks...
    public override FileStream method()
    {
        //...more stuff...
    }
}
thecoop
  • 45,220
  • 19
  • 132
  • 189
0

I hate having to type IEnumerable<MyType> all over the place. It is so hard to read. I would prefer some sort of short hand for it to make my code cleaner.

This SO post sums it up nicely.

Community
  • 1
  • 1
Brian Genisio
  • 47,787
  • 16
  • 124
  • 167
0

I find it enormously irritating that so many core methods are static, especially around commonly used stuff like Strings and Arrays.

Why:

Array.Sort(myArray);
String.IsNullOrEmpty(myString);

instead of:

myArray.Sort();
myString.IsNullOrEmpty

Not saying there aren't good reasons for it and it's not a big deal, but if JS can manage it, why can't C#? *

Also the switch implementation. I really think they should have trusted us with fallthrough.

* Come to that I miss JS's closure syntax too.

annakata
  • 74,572
  • 17
  • 113
  • 180
0

I don't like IDisposable/Dispose etc. Coming from C++ it is very annoying to find yourself having to think about memory management in C#. The using statement is fine if the disposable object is only used in one function. If it has to be passed around you need to manually reference count or do something else to to know when you can dispose the object.

Steven
  • 3,878
  • 3
  • 21
  • 21
0

I'd like to see class objects as first class objects in the language.

This would allow you to override static methods, and declare them in interfaces.

pgb
  • 24,813
  • 12
  • 83
  • 113