Ещё можно вполне документированно прогнать вызов через Remoting, начала получив через прокси экземпляр IMethodCallMessage, а затем в соседнем потоке отдав его на откуп RemotingServices.
Ну и unsafe-код с получением pinned-указателя и дальнейшей работой с T* тоже вполне документирован, да. Причём этот вариант более безопасен чем магия выше. А ещё лучше не колдовать вообще и сделать нормально, но это выходит за рамки темы вашей статьи, как я понимаю.
>>А ещё лучше не колдовать вообще и сделать нормально
Такой способ выходит за рамки тематики одного из указанных хабов. И одной из целей было обойтись без unsafe.
Изначальной целью был некий IDisposable, который бы сначала менял значение поля на какое-то временное, а на Dispose возвращал бы старое значение взад. Т.е. нужно в любом случае передавать ссылку на поле в другую область видимости. Если просто оставить преобразованный RuntimeArgumentHandle в статическом поле и преобразовать его обратно уже в другой области видимости (при том, что фрейм стека, в котором он был создан, уже «умер») то ArgIterator ничего не сможет вытащить — аргументов уже 0 (а при попытке получения количества оставшихся аргументов или при получении одного из аргументов можно уронить clr). С TypedReference при этом нечто похожее, и тоже можно уронить clr (правда, указатель, что является единственным полем, остаётся неравным нулю).
p.s. всё это катит только в дотнете, в Mono свои заморочки и такого фокуса я там пока не провернул.
В моно вообще весёлые вещи есть. Например, когда я писал кодогенерацию для одной штуки, то обнаружил, что .NET игнорирует разницу между ldfld и ldsfld, извлекая нужную информацию из FieldInfo, а вот Mono — нет. При этом ошибок никаких он не выдаст, а вместо статического поля загрузит нестатическое с тем же индексом. А пост-эффекты были просто замечательные, например, у меня в переменной типа List<int> лежал объект типа Action, что видно было лишь в отладчике, программа же валилась с SIGSEGV.
Количество таких историй может исчисляться тысячами. Например, используя в моно класс из другой сборки (собранной студийным компилятором), метод которой что возвращает T*, то Console.WriteLine (SomeMethod()) может отобразить… ничего. У меня такое было — такое чувство что вызов каким-то образом отменялся. Зато если преобразовывать указатель в строку и выбрасывать его как new Exception(someTakenString) то можно было этот указатель получить. Что интересно, можно такой фокус использовать без /unsafe в опциях компилятора, но использовать этот фокус с политикой, что требует security transparent код и никакой другой, то можно получить исключение, которое свидетельствует о том, что clr НЕ В СОСТОЯНИИ определить, является ли такой код типобезопасным. (Речь идёт о Unity3D, второй случай (с политиками безопасности) является случаем билда в веб-плеер).
Однако это есть правильно, потому что другой поток не может быть уверен, что он пишет по адресу который еще не очищен из-за выхода за предел видимости в родительском потоке. Очевидное решение — не хранить данные в value type классах/полях если хочется многопоточность.
По поводу же вашей изначальной цели: «некий IDisposable, который бы сначала менял значение поля на какое-то временное»
Можно просто хранить в IDisposable ваш класс и функтор, который изменяет поле. Класс, конечно, не должен быть структурой.
Недокументированные возможности недокументированных возможностей: Передача ref в другой поток