Tuesday, October 30, 2012

Lisp, here's why the mainstream ignores you.

While I currently don't know how you write a "hello world" in LISP, I am keenly aware that the LISP language, with its powerful macro system, could be very instructive on the topic of metaprogramming. However, it is proving difficult to quickly learn LISP because the community uses terminology, technology and notations that are far outside the mainstream.

The most obvious thing is the parenthesis. While a prefix notation such as
    (eqv? (* (+ (2 3)) x) 20)
    meaning (2 + 3) * x == 20
gives LISP its power as a programming language, it's also a huge turnoff. I can't figure out why they haven't standardized on a syntactic sugar such as sweet expressions that maps in a predictable way back to S-expressions. Even sweet expressions look a lot different than popular languages, but it's clearly an improvement.

I went looking for information on the macro system and the first search result for "LISP macros" is some university lecture notes. It suggests "macroexpand-1" as a debugging tool so I Googled that next, and came upon this page from Common Lisp the Language, 2nd Edition, which states:
A form is considered to be a macro call only if it is a cons whose car is a symbol that names a macro.
Ahh... say what? Well, I guess I can handle learning what a "cons" is (Wikipedia implies that a list like (1 2 3) is shorthand for the singly-linked list (cons 1 (cons 2 (cons 3 nil))), which is a bit surprising since everything in LISP is made out of lists, and the performance and memory consumption of singly-linked lists is known to be rather bad on modern 64-bit machines, but I digress...

Anyway it's slightly amazing that the terms "car" and "cdr" are still in use:
Lisp was originally implemented on the IBM 704 computer, in the late 1950s. The 704 hardware had special support for splitting a 36-bit machine word into four parts, an "address part" and "decrement part" of 15 bits each and a "prefix part" and "tag part" of three bits each.
...
  • car (short for "Contents of the Address part of Register number"),
  • cdr ("Contents of the Decrement part of Register number")
Considering that LISP was a potentially revolutionary idea, I can forgive it for using these terms... in 1959. But to be using them in the 21st century? It's a boneheaded way to alienate potential users.

I'm not totally new to car and cdr, I've seen it before, but I've had to look up car and cdr about three times now because I keep forgetting which one is which. I think I'll just remember that "a" is the first letter of the alphabet so "car" fetches the first item in a list, while "d"... well, "d" is a different letter of the alphabet. The Wikipedia article even seems to think these names are advantageous:
However, car and cdr have the advantage that short compositions of the functions can be given short and more or less pronounceable names of the same form. In Lisp, (cadr '(1 2 3)) is the equivalent of (car (cdr '(1 2 3))); its value is 2 (the first item of the rest of (1 2 3)). Similarly, (caar '((1 2) (3 4))) is the same as (car (car '((1 2) (3 4)))); its value is 1.
Riiiiight. So you could use "cadr" to mean "first of the rest" and you could use "caar" for "first of the first". Or, why not use something logical like "second" and "first.first". Or if brevity is really that important, "r.f" and "f.f" - but it's probably not that important.

So then I figured I'd download LISP and play around with it. I knew Common Lisp was a ... well, a common LISP, so I Googled that. The first four results were sites about common lisp without downloads; the third was the book Practical Common Lisp which suggested Lisp in a Box, linklessly. Searching for Lisp in a Box finds "LispBox" instead, although it might be the same thing: the book says Lisp in a Box uses emacs as its editor, while Lispbox's page says the same thing.

But I don't want to use emacs! I used that bastard a little in university a bit but ugh, it's just an ugly text window with a weird interface that is different from every editor that isn't emacs. Almost every other editor is standardized on Ctrl+S for Save, Ctrl+F for Find, Tab for indenting text, Ctrl+C for copy, etc. But not ugly old emacs, oh no. (Yeah, okay, macs prefer the ⌘ key... if I had a mac I'd probably have to remap it to Ctrl.)

They even have a different notation for keyboard shortcuts than everybody else: "C-h t" where the rest of the world would probably say "Ctrl+H, T" (except that the rest of the world wouldn't use multiple-key shortcuts for anything important.) Even worse, referring to the Alt key as "M-"? It's crazy, like they're waiting for the 80s LISP machines to come back.

Of course, if you're used to emacs then it must be the rest of the world that seems weird. But there's an easy solution: on first startup, emacs could offer a choice of "Traditional emacs keyboard interface" and "Normal keyboard interface (recommended for new users)", the latter being based on Windows and Mac programs. To decide how to assign other keys, they could copy bindings from the most popular IDEs, Visual Studio and Eclipse.

The Lispbox downloads are oddly headlined "Lispbox test builds", but whatever. So I download the Windows one--90 MB compressed? Son of a bitch! That's what happens when you choose emacs as your editor--okay, okay, it's only half of the total size, and maybe I'm being unfair since some IDEs are bigger, but wasn't LISP supposed to be lightweight?

Thankfully, emacs offers a "C-x/C-c/C-v Cut and Paste" option, but "Delete" still doesn't delete selected text, "Ctrl+F" doesn't work and "Ctrl+Z" minimizes the damn window, and maybe worst of all, "Tab" either doesn't do anything or indents by a seemingly random amount, depending on the context (I'll figure that out later).

It's getting late, maybe I'll finish this later... if anyone can name a non-emacs LISP environment, I'd like to know.
----

The key problem I'm facing right now in my exploratory design of macros for EC# is the question of how to order macro expansions with respect to each other and with respect to substitution operations (which, for all I know, should themselves be implemented with macros) and what the rules for name resolution should be. However, reading about LISP has provided little insight so far, because (1) I would have to understand LISP fairly well in order to understand the documentation about macros, or extremely well in order to understand any technical specifications; and (2) in tutorial-level material, the ordering of operations, the name resolution rules, and the compilation model are implicit and assumed to be of secondary importance. Quite reasonably they assume you want to use LISP, whereas I just want to shamelessly copy the ideas behind LISP and the lessons that were learned in the course of developing modern LISPs.

Perhaps this will help me. Since much of LISP is defined with macros, I had also been wondering which parts of LISP were built-in and which were macros. The key to finding this out seems to be the term "special operator" aka "special form", which is like a keyword or built-in statement in other languages. So far I haven't found a complete list of them though.

Wednesday, September 12, 2012

Opus, the codec to end all codecs

Opus is a new all-purpose low-latency audio codec with better quality than MP3 and better than Vorbis at low bitrates. Plus it's an open standard, open source, and patent-free! Not only that, it operates over bitrates from 6 kbps (for low-quality speech) up to 510 kpbs. Thus it is suitable to replace virtually every audio codec in the world!* As a bonus, it's an official IETF standard and it has been chosen a mandatory-to-implement (MTI) codec for WebRTC, an upcoming standard for real-time communication on the web.

Well, I had a look at the RFC. The technical details are largely impenetrable… for example the introduction to Range Coding should really say something about what fl[k], fh[k], and ft represent (and what’s [k], an array subscript?), and they really should not have waited until section 4.1.3.3 to introduce the concept of a Probability Density Function, since it appears to be a fundamental idea...

...Anyway, Opus is basically two codecs in one: a linear prediction (LP) codec for speech (based on a standalone codec called ‘SILK’) and a MDCT-based codec for music (based on a standalone codec called ‘CELT’). An Opus encoder can instantly and seamlessly switch between the two codecs at any time according to the bitrate and the dominant character of the input, and there is a hybrid mode where SILK is used for low frequencies and CELT for high frequencies.

CELT is built on the same psychoacoustic principles as other modern codecs (e.g. Vorbis), but adds innovations to permit low latency without hurting overall audio quality. SILK is designed for low bandwidth and low-latency speech (though the principles behind it remain totally opaque to me), while CELT is better for high bandwidth audio (music or speech or anything else) but can still operate at very low bitrates when the sound is not speech or speech-like and therefore unsuitable for SILK.

The operating modes of Opus are designed so that the two codecs “fit together” nicely, and it can switch between the two on 10ms boundaries (sampling range can similarly change among 8/12/16/24/48 kHz, ditto for mono/stereo). Opus also offers other real-time and VOIP features, such as CBR and forward error correction and other tricks to compensate for packet loss.

Some final niceties of Opus: the encoder and decoder can operate at independent sampling rates (or one can be mono and the other stereo), and the (continuously variable) bitrate is independent of the operating mode (e.g. want stereo at 48 kHz at 8 kbps? It’s probably a bad idea, but it’s not outright prohibited). So basically Opus covers virtually all scenarios. The codec to end all codecs, indeed. (correct me if I’m wrong about any of this, dear experts).

Now can I just get a codec that achieves very low bitrates by observing long-term audio patterns and making backward references to similar audio many seconds in the past? kthxbye :) Codec2 (presentation) is really fascinating too. It was developed for radio applications, and is not really useful for VOIP because Codec2 packets are much smaller than UDP headers, i.e. the overhead of the Internet itself outweighs the space savings of Codec2. But what I find interesting about it is the potential for cheap archiving. For instance, with Codec2 you could record your entire life: at 2400 bits/second it requires just 25.9 MB (non-MiB) per day and 9.46 GB per year or under 1 TB for a lifetime (or much less, assuming you eliminate regions of silence and reduce the bitrate in nearly-silent situations.) Coupled with voice recognition and a search index, you'd finally be able to resolve any arguments with your wife about who said what last week. I bet some sociologists and linguists would find interesting uses for such a corpus...

Tuesday, July 17, 2012

Constructors Considered Harmful

Ahh, constructors, constructors. In my opinion the constructor design in most languages including C++, C#, D and Java is flawed, because it exposes an implementation detail that should not be exposed, namely, which class gets allocated and when.

I offer you as "exhibit L" the Lazy<T> class in the .NET framework. This class's main purpose is to compute a value the first time you access it. For example:
 int x;
 Lazy<int> lazy = new Lazy<int>(() => 7 * x);
 x = 3;
 x = lazy.Value; // 21
 x = lazy.Value; // still 21 (Value is initialized only once)}
There is an annoying issue, though: Lazy<T> operates in some different modes, and it also contains a member and extra code to aid debugging. So in addition to holding the value itself and a reference to the initializer delegate, it's got a couple of other member variables and the Value property has to check a couple of things before it returns the value. Thus, Lazy<T> is less efficient than it should be.

So what if, in the future, MS decided to optimize Lazy<T> for its default mode of operation, and factor out other modes into derived class(es)? Well, they can't ever do that. If MS wants to return a LazyThreadSafe<T> object (derived from Lazy<T>) when the user requests the thread-safe mode, they can't do that because all the clients are saying "new Lazy", which can only return the exact class Lazy and nothing else.

MS could add a static function, Lazy.New(...) but it's too late now that the interface is already defined with all those public constructors.

As "exhibit 2", a.k.a. "exhibit Foo", I recently wrote a library where I needed to provide a constructor that does a bunch of initialization work (that may fail) before it actually creates the object. By far the most natural implementation was a static member function:
 // Constructor with dependency injection
 public Foo(A arg1, B arg2, C arg3)
 {
 }
 // Static helper method provides an easier way to create Foo
 public static Foo LoadFrom(string filename, ...)
 {
     ... // do some work
     arg1 = ...; arg2 = ...; arg3 = ...;
     return new Foo(arg1, arg2, arg3);
 }
However, the client didn't like that, and insisted that LoadFrom() should be a constructor "for consistency" with the other constructors. I was able to rearrange things to make LoadFrom() into a constructor, but my code was a little clunkier that way.

So what I'm saying is, when clients directly allocate memory themselves with new(), it constrains the class implementation to work a certain way, and this constraint is unnecessary.

A final problem with constructors is that they can't have names.

For D I suggested a simple solution, which in principle could be added to any language that uses "new". The solution is to treat constructors as equivalent to static methods named "new". So when the user writes "new Foo(...)", this call might go to a real constructor, or it could go to a static method named "new" that returns a Foo. Likewise, if the user writes "Foo.new(...)", this call could go to a static method or to an actual constructor.

This tweak would allow the class Foo to change the implementation of a constructor to return an object derived from Foo, instead of Foo itself. It would also allow Foo to do some work before actually creating a Foo object. Finally, this proposal doesn't allow named constructors per se, but it does provide a similar syntax for named and unnamed creation methods, because the syntax to call an unnamed constructor, "Foo.new(...)" is similar to the syntax to call a named creation method, "Foo.newFromFile(...)".

I don't expect D or any other language to accept my proposal, but it's a good idea so I'm blogging it anyway. In .NET, this feature would be more practical if .NET compilers were to automatically create a static "new" method for every real constructor, and to prefer to emit calls to the static method (if present) instead of the real constructor. This rule would provide for binary compatibility, which improves upon the source-level compatibility provided by my syntax proposal.

Tuesday, June 19, 2012

NDK Docs

Google has not placed its NDK documentation online. Consequently any NDK-related Google searches that might by answered by the NDK documentation will come up empty. I'm tired of this, so I've decided to put up some of these docs, at least the ones that are not mirrored elsewhere already.

Friday, June 15, 2012

Android ListView: Make Selection Stay

The behavior of Android's ListView is surprising: when the user clicks an item, it doesn't stay selected! It looks selected for a brief instant and then fades away.

Apparently the "disappearing selection" is by design; it's something called "touch mode". I read through that document and still I have no idea why they thought it was a good idea. My guess is that, since Android was originally designed for small-screen devices, they expected that you would fill the screen with a list and then, when the user clicks an item, move to a new list on a different screen. Thus, the user wouldn't be aware that Android lost track of the selected item.

But this behavior is quite annoying if, for example, you want the user to select an item and then show information about that item on the same screen. If the selection disappears, how is the user supposed to know what they clicked (assuming of course that users have the attention span of a goldfish)?

One possible solution is to change all the list items into radio buttons. I don't really like that solution because it wastes screen real estate. I'd rather just use the background color to show which item is selected. I have seen one solution so far but it is not quite complete or general. So here's my solution:

1. In your XML layout file,

Go to your ListView element and the following attribute: android:choiceMode="singleChoice". I'm not entirely sure what this does (by itself, it doesn't allow the user to select anything) but without this attribute, the code below doesn't work.

2. Define the following class.

It is used to keep track of the selected item, and also allows you to simulate pass-by-reference in Java:

public class IntHolder {
public int value;
public IntHolder() {}
public IntHolder(int v) { value = v; }
}

3. Put the following code somewhere

I'll assume you put it in your Activity, but it could go in any class really:
static void setListItems(Context context, AdapterView listView, List listItems, final IntHolder selectedPosition)
{
    setListItems(context, listView, listItems, selectedPosition, 
                 android.R.layout.simple_list_item_1, 
                 android.R.layout.simple_spinner_dropdown_item);
}
static void setListItems(Context context, AdapterView listView, List listItems, final IntHolder selectedPosition, 
                         int list_item_id, int dropdown_id)
{
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> list, View lv, int position, long id) {
            selectedPosition.value = position;
        }
    });
    ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(context, list_item_id, listItems) { 
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View itemView = super.getView(position, convertView, parent);
            if (selectedPosition.value == position)
                itemView.setBackgroundColor(0xA0FF8000); // orange
            else
                itemView.setBackgroundColor(Color.TRANSPARENT);
            return itemView;
        }
    };
    adapter.setDropDownViewResource(dropdown_id);
    listView.setAdapter(adapter);
}

That's all! The above assumes you want single selection. With some small modifications to getView(), you could support multi-selection too, I guess, but you should probably use checkboxes instead.

Warning: this solution needs further development. If the user uses arrow keys or buttons to select an item, that item will not be selected from the IntHolder's perspective. If the user presses the unlabeled button or the Enter key then the item will become "officially" selected, but then you have another problem because if the user uses the arrow keys again, it will sort of look like two items are selected. Leave a comment if you figure out how to keep the "internal selection" in the IntHolder synchronized with the "keyboard selection" or whatever it's called. What is it called, anyway?

Friday, June 8, 2012

The Delightful D Programming Language

D versus C# and C++

I became a D enthusiast yesterday, when I learned how much better it is than C++, and I have been studying D for two days straight out of sheer love. Oh, it's not perfect, but compared to C++? No contest. Ditto for Java. C# was my language of choice as of 3 days ago, but today I think it has moved down a rank.

Not having used D for any serious work yet, I could be mistaken. But D has an answer to every major criticism commonly raised against C++, from compilation time, to poor type safety, to the headache of maintaining header files, to slow compilation. D isn't just an evolutionary improvement, it has innovations that don't exist in any of the world's popular languages*:
  • It is said to have one of the world's fastest compilers
  • You can use try/catch/finally and RAII, but scope(exit) makes exception-safe code easier to read and write
  • You can define closures that the compiler can inline (do any C++11 compilers do that? I'm not sure, I'm stuck on Visual C++ 2008 due to a need to support Windows CE)
  • Garbage Collection is standard but optional, so you can write programs with low-latency guarantees by avoiding GC allocations (but how to manage memory instead? I suspect one could use alias this to make smart pointers a la C++?)
  • Slices and ranges, a collection access mechanism that is far safer than C++ iterators and also far more convenient, no need to repeat yourself as in lower_bound(blobCollection.begin(), blobCollection.end(), blob)
  • Generics are more flexible than in C++ and don't produce pages of error messages
  • Compile-time metaprogramming that vastly outclasses C++ (and obviously C# too)
  • Compile-time reflection which (I hope, but can't confirm) one could use to build a run-time reflection system if one wanted
  • A well-designed, multi-paradigm approach to concurrency with interesting features for both shared-memory and message-passing architectures
  • Built-in support for unit tests
  • Array-wise expressions, e.g. a[] = (b[] + c[]) / 2  (MATLAB does this more tersely, but among general-purpose languages this kind of feature is rare)
  • Superior floating-point features (e.g. nextUp()/nextDown()/ulp(), hex floats, control of hardware exceptions)
* (Other less-popular languages have some of these features, but certainly not all of them)

And since D is so similar to C++ and C#, you wouldn't have to spend a lot of time learning it, so why not? Plus, it shouldn't be that hard to port small programs and libraries from C++.

Admittedly, I'm not happy with everything. They are still catering to the C crowd, so you still have to fill your "switch" statements with "breaks", the "static" keyword is confusingly overused, lambdas require braces and a "return" statement (c.f. C#'s quick x -> x+1 syntax), all functions and try/catches requires braces, pass-by-reference is implicit at the call site, the operator precedence of (&, |, ^) is foolish, there's no pattern matching or algebraic data types (but at least there are tuples), if statements are not expressions... still, what D offers is too good to pass up.

But of course, while the D language is clearly terrific, and the standard library has apparently matured, the surrounding tools might not be so good: IDEs, support for smartphone platforms, etc. The only IDE I tried, Visual D (IDE plugin for Visual Studio) works pretty well, including debugging which seems to work as well as the Visual C++ debugger, and which can step into the standard library (fun!). However, Code Completion doesn't work very well yet.

Compared to C#, D is better in most areas but seems weak when it comes to dynamic linking and reflection. For example, an IDE written in .NET or Java could easily have a plug-in system, but I'm not so sure about D. .NET also offers runtime code generation while D does not. However, a research compiler exists to compile D to .NET code. Given that C++/CLI already compiles to .NET (C++/CLI), perhaps someday one will be able use D equally well for managed and native code (with a small performance hit in managed land, of course.)

Interoperability with C/C++ and .NET are pretty decent. D is supposed to interoperate with C++ functions and singly-inherited classes via extern (C++) and C++ name mangling (but which compiler's name mangling?), while you can easily create COM interfaces callable from .NET and other languages.

Still don't know D? Go forth and learn it! Note: okay, to be honest the documentation isn't that great. It really helps to read The D Programming Language.

Thursday, June 7, 2012

Smart Tabs

Man, I sure wish programming text editors would support those smart tabs known as "elastic tabs".


Use Visual Studio? Vote for elastic tabs.

Thursday, April 5, 2012

Shouldn't you learn that new Microsoft API?

I recently responded to someone trying to justify learning all those newfandangled Microsoft APIs. It sounded like a blog entry so I'm copy-pasting here.

While you should definitely learn some of the new MS technologies, my recent experience learning about things like WPF and WCF has made me a bit more cautious about learning the newest MS APIs.

Now, LINQ is a major boon to productivity that you should definitely be using; the nice thing is that you can introduce LINQ-to-objects piecemeal in all sorts of random situations, with or without the actual query syntax (I commonly call `Where()` without the `from-select` syntax, as it is often shorter.) The mathematical dual of LINQ, Reactive Extensions, is something you should be aware of, although I am still struggling to find a really good use case. Likewise, all features of C# 3/4/5 are useful so you should study them and watch for places where they will be useful, even as you continue using the "old" BCL stuff.

However, I'm going to take devil's advocate and suggest that the very newest and biggest MS libraries, such as WCF and WPF are not necessarily worth learning at all.

The primary reason is that they are huge, and not especially well-designed (the former being a symptom of the latter). I briefly blogged recently about why WPF sucks. As for WCF, the whitepaper makes it sound like it will easily interoperate nicely with "Java EE server running on a non-Windows system" and "Partner applications running on a variety of platforms", but the truth is that WCF APIs are very specifically SOAP-oriented and have very limited support for non-SOAP protocols. MS could have easily designed a general system that allows pluggable protocols, and maybe the capability is hidden (undocumented) in there somewhere, but as far as I can tell they chose to design a much more limited system that can only do SOAP and limited HTTP (as long as your message body is a serialized .NET object, IIRC). I researched Entity Framework more briefly, but noticed some complaints that it was incapable of supporting some scenarios that the (much simpler) LINQ-to-SQL can handle out-of-the-box.

IMO the design of all of these libraries are fundamentally flawed because they use a lot of components that are tightly coupled to each other, a dependency graph of the classes in each framework would probably be huge and look like a jumbled mess of scribbly lines. And even if the design were good, we would not be able to tell because there aren't public architectural documents that delve into the lower-level details, and the MSDN docs for the most part aren't very good (they tend to get less and less helpful as you look at lower and lower-level classes.)

The sheer size of the libraries also seems like a flaw; I have learned over 20 years of programming that simplicity is a virtue, one that Microsoft has never valued.

But you might ask, "so what"? Well, with such big libraries you might never feel like you really understand them. That means that when you want to do something outside the use cases for which Microsoft specifically designed WCF/WPF/EF, you're not going to know how, and it is possible that no one outside Redmond will know how, either. And when something goes wrong, you will have a hard time figuring out what went wrong. And 15 years from now when Microsoft has moved on to their next next-generation API, no one is going to enjoy maintaining software built on a foundation that is so poorly-understood.

Also because of the largeness and complexity of these new APIs, the cross-platform alternative to .NET, Mono, has poor support or no support for them. You'll probably have little difficulty using your typed data tables on Linux or Mac, but Entity Framework? Forget about it. I wouldn't be surprised if Mono never supports it.

I have used LINQ-to-SQL in a new project and it's not bad. In some ways it could be better, but I think the developer experience is substantially better than ADO.NET. One significant limitation: L2S is easiest by far if you modify tables in "connected" mode, unlike the old ADO.NET which was specifically designed to work without an active database connection. Anyway, since LINQ-to-SQL is (according to Mono people) a quarter the size of Entity Framework, it's a shame that MS decided to quit working on it.

Saturday, February 25, 2012

Design flaws in .NET

I made this list of the flaws in .NET for StackOverflow, but then I noticed that the question is closed. Whatever, I may as well CC to my blog. All of these flaws except #3 have irked me personally. .NET is my favorite platform, yet it is still far from ideal.
  1. There are no subsets of ICollection<T> and IList<T>; at minimum, a covariant read-only collection interface IListSource<out T> (with an enumerator, indexer and Count) would have been extremely useful.

  2. .NET does not support weak delegates. The workarounds are clumsy at best, and listener-side workarounds are impossible in partial trust (ReflectionPermission is required).

  3. Generic interface unification is forbidden even when it makes sense and cause no problems.

  4. Unlike in C++, covariant return types are not allowed in .NET

  5. It is not possible to bitwise-compare two value types for equality. In a functional "persistent" data structure, I was writing a Transform(Sequence<T>, Func<T,T>) function that needed to quickly determine whether the function returns the same value or a different value. If the function does not modify most/all of its arguments, then the output sequence can share some/all memory from the input sequence. Without the ability to bitwise compare any value type T, a much slower comparison must be used, which hurts performance tremendously.

  6. .NET doesn't seem able to support ad-hoc interfaces (like those offered in Go or Rust) in a performant manner. Such interfaces would have allowed you to cast List<T> to a hypothetical IListSource<U> (where T:U) even though the class doesn't explicitly implement that interface. There are at least three different libraries (written independently) to supply this functionality (with performance drawbacks, of course--if a perfect workaround were possible, it wouldn't be fair to call it a flaw in .NET).

  7. Other performance issues: IEnumerator requires two interface calls per iteration. Plain method pointers (IntPtr-sized open delegates) or value-typed delegates (IntPtr*2) are not possible. Fixed-size arrays (of arbitrary type T) cannot be embedded inside classes. There is no WeakReference<T> (you can easily write your own, but it will use casts internally.)

  8. The fact that identical delegate types are considered incompatible (no implicit conversion) has been a nuisance for me on some occasions (e.g. Predicate<T> vs Func<T,bool>). I often wish we could have structural typing for interfaces and delegates, to achieve looser coupling between components, because in .NET it is not enough for classes in independent DLLs to implement the same interface--they must also share a common reference to a third DLL that defines the interface.

  9. DBNull.Value exists even though null would have served the same purpose equally well.

  10. C# has no ??= operator; you must write variable = variable ?? value. Indeed, there are a few places in C# that needlessly lack symmetry. For example you can write if (x) y(); else z(); (without braces), but you can't write try y(); finally z();.

  11. When creating a thread, it is impossible to cause the child thread to inherit thread-local values from the parent thread. Not only does the BCL not support this, but you can't implement it yourself unless you create all threads manually; even if there were a thread-creation event, .NET can't tell you the "parents" or "children" of a given thread.

  12. The fact that there are two different length attributes for different data types, "Length" and "Count", is a minor nuisance.

  13. I could go on and on forever about the poor design of WPF... and WCF (though quite useful for some scenarios) is also full of warts. In general, the bloatedness, unintuitiveness, and limited documentation of many of the BCL's newer sublibraries makes me reluctant to use them. A lot of the new stuff could have been far simpler, smaller, easier to use and understand, more loosely coupled, better-documented, applicable to more use cases, faster, and/or more strongly typed.

  14. I'm often been bitten by the needless coupling between property getters and setters: In a derived class or derived interface, you can't simply add a setter when the base class or base interface only has a getter; if you override a getter then you are not allowed to define a setter; and you can't define the setter as virtual but the getter as non-virtual.