다음을 통해 공유


Some code patterns I don't love in C#.

Pattern 1: TryGetFoo that returns boolean.

MyEnum ret;
if (Enum.TryParse<MyEnum>(normalized, true, out ret)) { return ret; } else { return null; }

You would think this slightly more concise line would work

MyEnum ret;
return Enum.TryParse<MyEnum>(str, true, out ret) ? ret : null;

But it turns out that is no good. Compiling the ternary operator, compiler can't even figure out the common type of null and MyEnum is Nullable<MyEnum>!

Either way, what's not to love? Having to declare a throwaway out parameter. Having to explicitly marshal boolean true into value, and boolean false into null. And enums themself. Which are not nullable. Luckily nullable enums (MyEnum?) come to the rescue by being nullable... but they are a different type, so you have to think about which to use when.

If javascript had enums it would probably be like:

return enumType.TryParse(str, true);

Of course javascript doesn't really have enums, so the function might either be returning some object, some string, or some number. But the point of parsing here is that at least you know it's constrained to a set of certain fixed values.
 

Pattern 2: is/as/casting.

if (reader.Value is Foo)
{
(reader.Value as Foo).doSomething();
}

If only the compiler and intellisense could auto-infer the Fooness in this scenario... of course there are reasons to do with method overloading that this would sometimes realy suck too.
Speaking of method overloading...

Pattern 3: many slightly different method overloads with optional parameters

LogException(a, b = null, c = null, d = null)
LogException(a, e, f = null)

The thing I don't like about this pattern is that it always turns out that the particular parameters you want to use are not quite matching up with the order/selection of parameters that someone else thought would make good defaults.
To me it's awesome how this one gets solved in javascript. Parameter objects to the rescue!
LogException({ a: x, b: y, f: z});
Now you no longer have artificial strictures on which orders and subsets of parameters are valid to supply. Only the function logic itself will govern this (by throwing if it really must)
Of course for that to work, someone had to try hard to make one function work for all possible parameter sets. But at least there's much saved stress in the process of consumption. :-P

Now that I've written this rant, happy coincidence! It may have jogged my mind towards figuring out a little bug I was having related to enums and nullability. I put [JsonConverter] attribute on an enum type MaxMemoryPolicy. However, when my properties are of type [MaxMemoryPolicy?] I don't think the converter was getting called in the serialize string to nullable enum direction - hey, type mismatch! Let's just convert it to null and see if we can assign that... Yup? Cool! Arggggg.
Now some debugging will confirm or deny this new hypothesis... denied. OK it was something else. But I had to consider the possibility. :p

Comments

  • Anonymous
    August 29, 2014
    I'm confused about your last point. C# has named parameters. I use them all the time.

  • Anonymous
    August 31, 2014
    You should try ServiceStack's Json serializer. It works with nullable enums.