There are some things about C#’s syntax that really get to me. Here is one of them.. I just hate the way it reads and makes the intention of the code so much more difficult to understand.
[Test, ExpectedException(typeof(ArgumentNullException))]
public void GetAllFilesMatching_With_NullPath_ThrowsArgumentNullException()
{
foreach (string s in DirectoryWalker.GetAllFilesMatching(null, AlwaysTruePredicate)) { }
}
Yuck… Whats your favorite Syntactical Molasses in C#?
I found myself doing this one day:
List list = new List ();
double sum = 0;
list.ForEach(delegate(ITran t) { sum += t.Amount; });
Then slapped myself and changed it to use a real for loop.
My favorite was the “toArray” method of ArrayList.
http://www.lazycoder.com/weblog/index.php/tips/arraylisttoarray/
“That’s ok, but now you have an ArrayList, not an array of type “Group”. Luckily you can use the ToArray() method of the ArrayList class to convert it to a Group array. There is a catch though. Even though you pass in a type (”Group”) it returns an array of objects. You need to explicitly cast it as the type you want the array to be of.
arGroups = (Group[]) listGroups.ToArray(typeof(Group));
”
Generics killed this little bit of heaven.
matt:
You say the foreach should be an iterate method … is it any clearer with
IterationOver(DirectoryWalker.GetAllFilesMatching(null, AlwaysTruePredicate))
WHY I am iterating over something that should fail in a precondition?
if this is a List returned as an IEnumerable it throws an exception up front when I call the GetAllFilesMatching method and iterateover is never called.
That’s nothing to do with C#. It’s just poor API design in the test framework (use of attributes, not objects or functions) and poor test code (the foreach is *how* the tested behaviour is triggered, but does not communicate why).
How about:
AssertThrows(typeof(ArgumentNullException), delegate {
IterationOver(DirectoryWalker.GetAllFilesMatching(null, AlwaysTruePredicate));
});
Or with a bit of refactoring:
AssertThat(delegate{
IterationOver(DirectoryWalker.GetAllFilesMatching(null, AlwaysTruePredicate))},
ThrowsException(typeof(ArgumentNullException)));
Generics can get pretty sticky when you have anything that might be nested. Like if you find yourself in this situation:
Dictionary> itemDict = new Dictionary >();
Better?
var files = DirectoryWalker.GetAllFilesMatching(null, s => true);
Indeed, WRT “break”. If the language will give me an error that the break is missing, it knows exactly where it should be; so I don’t need it. It’s not like C++ where you can fall through to the next case…
Similar to “Error: missilng semicolon”. Well, then put the damn semicolon in then!
I see ‘syntactical molasses’ every day, but it’s not the language’s fault. No matter what they tell you, it’s a people problem, right ?
Sure, some languages are more verbose than others (in my personal experience, Java was the most verbose I ever encountered), but it’s up to the developers to make good or bad use of the language. No ?
I find the required ‘break;’ after a case clause the most stupid thing I’ve ever seen in a language. It’s completely redundant: there’s no fall-through, so there’s never going to be a case clause which flows through into the next one. Still a break is required. If you don’t specify a break, the compiler whines that there’s no fall through (duh!) and a break is required, but … that’s not necessary, there’s no fall through, csc!
My favorite is the null != DBNull.Value fiasco that increases the complexity of working with data access logic. Because of this blunder, simple code like this
decimal cost = (decimal) reader["Cost"] ?? 0;
actually reads like a Daily WTF submission
decimal cost = (decimal) (reader["Cost"] != DBNull.Value ? reader["Cost"] : 0);
How about:
TypeOfEnum enumValue = (TypeOfEnum) Enum.Parse(typeof(TypeOfEnum), someValue);
and I really want hashtables to be prettier:
Dictionary d = new Dictionary ();javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(“ctl00$ctl00$ctl00$bcr$bcr$bcr$ctl14$ctl02$ctl02$ctl02$btnSubmit”, “”, true, “CreateCommentForm”, “”, false, true))
Add
d.Add(“blah”, blah”);
d.Add(“blah2″, blah2″);
CallSomeMethod(d);
… as opposed to something more boo-like:
CallSomeMethod({“blah”: “blah”, “blah2″ : “blah2″});
On another note, don’t you have issues with refactoring with your test naming convention? I used to dread renaming methods or properties, as I would have to manually fix all of the test names pertaining to that test.
Molasses eh… Let’s see. I dislike inline anonymous delegates in method calls. Seeing “})” just looks strange.
I also dislike full syntax for lambdas (no type inference).
I absolutely hate that {} is required for single line try/catch.
And, finally, why the heck do I have to break out of the last block in a switch.
With regard to Greg’s blog post code, and *why* he needs the foreach (or more specifically, a call to IEnumerator.MoveNext) see:
http://blogs.msdn.com/ericlippert/archive/2007/09/05/psychic-debugging-part-one.aspx
http://blogs.msdn.com/ericlippert/archive/2007/09/05/psychic-debugging-part-two.aspx
Chris you can’t “just call” it … the method doesn’t get called until the enumerator gets called …
with just this…
DirectoryWalker.GetAllFilesMatching(null, AlwaysTruePredicate)
The test fails as it never gets called
I could do something like IEnumerable<string> s = … then call MoveNext() but thats quite weird too …
One of the annoying syntax thing for me in C# is the class / ctor syntax.
Public class MyClass
{
public MyClass(){}
}
Why do I need to type “MyClass” twice? (or 3 times, or 10 times).
(Prior to C# 3, the most annoying syntax for me was Property Accessors. Talk about excessive typing for no good reason!)
I gotta go with Peter – I don’t get why the ForEach is there. Even given the iterator signature of the method you’re calling, I think it’s just obscuring the purpose of the test.
Just Call:
GetAllFilesMatching(null, AlwaysTruePredicate)
yeah I guess its not obvious … here is the method signature being tested … it will make alot more sense.
public IEnumerable GetAllFilesMatching(string Path, Predicate Predicate)
In case anyone is wondering, why does Greg need the foreach if he just wants to see if GetAllFilesMatching throws an exception with a null argument?