?

Log in

No account? Create an account

November 21st, 2009 - Excelsior — LiveJournal

Nov. 21st, 2009

07:02 pm - Ортогональность

Приятно, когда у языка много фич, но еще приятнее, когда эти фичи ортогональны. Представьте задачу, которую надо реализовать на C# 4.0 - есть динамический объект, для него надо объявить read/write индексер, который экспозит его методы. И из-за того, что фичи языка фигово состыкованы в компиляторе, я вместо того, чтобы написать "o.Methods["Add"] = (int x, int y) => x + y", вынужден писать синтаксический шум: "o.Methods()["Add"] = Helpers.λ((int x, int y) => x + y)". Я потратил на хаки часа 2-3, но ничего так и не помогло, ибо компилятор сишарпа, бездушная машина, забанил все входы и выходы. Очень разочаровывает, что после стольких извращений приходится сдаться.

Первый подход заключался в том, чтобы объявить индексер вот так: "CallSite this[String]" и написать пачку имплисит кастов из всяких фанков в CallSite. В сишарпе генерик касты объявить нельзя, поэтому пришлось генерить IL и референсить сборку. Фейл - компилер не может вывести тип лямбды.

Второй подход был умнее - раз касты недостаточны, объявлю-ка я оператор "+" и напишу через "+=". Опять же, генерик операторы объявить нельзя, поэтому пришлось воспользоваться рефлекшн-эмитом еще раз. В результате, компилер сказал, что не может вывести типы, а решарпер упал с прикольным исключением.

Третий подход - задекларить пачку write-only пропертей, которые различаются лишь возвращаемым значением. В теории, из оверлоадов set_Item(String, Tk) можно однозначно выбрать нужный, если Tk все различны. Но, похоже, у компилера свое мнение на этот счет - еще один фейл. Позже до меня дошло, что этот подход бы все равно обломался, так как проперти не могут быть генерик, а для работы с экшнами/фанками это жизненно необходимо. Дабл фейл.

Наконец, от безысходности я решил не объявлять проперти, а сгенерить только пачку генерик сеттеров и навесить на тип атрибут [DefaultMember("Item")]. Но и таким образом не удалось обмануть компилятор - он сказал, что не может применить индексацию, ибо не нашел индексер. Эпик фейл.

Tags:
Previous day (Calendar) Next day